当前位置: 首页>编程语言>正文

springcloud acpect后置通知获取返回结果 spring 后置处理器


文章目录

  • 前言
  • 一、后置处理器是什么?
  • BeanFactoryPostProcessor
  • BeanPostProcessor
  • 二、后置处理器是如何工作的
  • BeanFactoryPostProcessor
  • Spring是如何使用的
  • 第三方整合Sring
  • BeanPostProcessor
  • Spring是如何使用的
  • 总结



前言

近日在重读Spring源码时,忽然有种打通任督二脉的感觉,有点慢慢摸到了Spring的设计精妙之处。后置处理器,相信对Spring稍有深入一些了解的同学多少都会知道。但是你知道为什么Spring要设计这个?这个东西的作用是什么?在整个IOC容器,甚至在整个Spring王国中的意义是什么?而这设计思路的背后,反映的是什么设计思想?
这里先卖个关子,本文中我会提出自己的拙见,欢迎大佬指点。此处只是想提醒下大家,在阅读的时候,应当带着目的。而且尽量多读几遍,因为第一次读的时候,很多东西无法联系起来思考和串联。


一、后置处理器是什么?

后置处理器分两大类:
一是:BeanFactoryPostProcessor
一是:BeanPostProcessor。

BeanFactoryPostProcessor

先看看官方解释:

/**
 * Factory hook that allows for custom modification of an application context's
 * bean definitions, adapting the bean property values of the context's underlying
 * bean factory.

大意就是:允许自定义修改应用程序的上下文bean定义,调整BeanFactory的属性配置,的上下文的工厂钩子。
可能有点绕,意思是说,这是上下文bean工厂的工厂钩子。什么意思呢?模板模式大家知道吧?模板模式里面钩子方法有了解吧。这个东西的可以类比理解为在上下文的bean工厂的模式里钩子方法。
那么,这个“钩子方法”可以干什么呢?

  1. 允许自定义修改应用程序的上下文bean定义
  2. 修改BeanFactory的属性配置

BeanPostProcessor

同样的,我们看看官方注释

* Factory hook that allows for custom modification of new bean instances —
 * for example, checking for marker interfaces or wrapping beans with proxies.

大意是:允许自定义修改新bean实例的工厂钩子,例如,检查标记接口或用代理包装bean。
这也是个“工厂钩子”,但与上面说的不一样,修改的是bean实例。


二、后置处理器是如何工作的

在回答这个问题之前,我们先来看看Bean的生命周期,我把Bean的声明周期分为4个阶段:

  1. Bean定义阶段:通俗点就是怀上了
  2. Bean实例化阶段
  3. Bean初始化阶段
  4. Bean销毁阶段

而处于不同目的/作用设计的后置处理器,工作在不同的阶段。

BeanFactoryPostProcessor

为了修改工厂中的Bean定义的BeanFactoryPostProcessor,工作在Bean定义阶段。注意,这里说的修改工厂中的Bean定义,不是修改某一个对象的bean定义,而是修改工厂中的bean定义。例如:增加bean定义-向容器中声明一个对象。这也是他与BeanPostProcessor的能力的重大区别之一。

Spring是如何使用的

以AnnotationConfigServletWebApplicationContext为例,Spring在上下文构建时,在构造器中创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,以不同的方式扫描注册配置类,并且都会向容器中注入真正完成我们自定义的Bean的扫描和注册的BeanFactoryPostProcessor,以及功能强大的Bean修改和调用操作的BeanPostProcessor!
这里重点认识一下:ConfigurationClassPostProcessor。他就是幕后英雄,扫描所有的@Component(包括@Configuration),并注册到上下文。

第三方整合Sring

BeanFactoryPostProcessor对于第三方整合Spring的实际意义,主要是自定义注解来声明Bean。这个与Spring自己的ConfigurationClassPostProcessor是类似的思路。
以Dubbo的整合为例:
Dubbo对其自定的注解就是通过他自己定义的BeanFactoryPostProcessorcom.alibaba.dubbo.config.spring.AnnotationBean,来完成的(当然,这个也是BeanPostProcessor,只不过这里的关注点不是他)

对于第三方整合而言,还有另外一个选择:@Import。这个注解能力也很强悍。导入一份配置,常用的@Configuration就不说了,还有ImportSelector、ImportBeanDefinitionRegistrar。同样也可以向容器中添加bean定义。值得一提的是,他是由ConfigurationClassPostProcessor来调用处理的。你也可以把他当成这个后置处理器的钩子。似乎更多的第三方整合方案偏好这个方案。或许因为它可以避免与Spring自己的后置处理器的执行顺序问题吧,使用一把小钩子就行了。

BeanPostProcessor

与BeanFactoryPostProcessor不同,BeanPostProcessor工作在bean的初始化阶段。在这个阶段,Bean已经创建完成,并且属性已经注入了。他的两个接口方法,分别在初始化之前和初始化之后执行。

我在官网上找到的一张关于Bean的生命周期的图。

springcloud acpect后置通知获取返回结果 spring 后置处理器,springcloud acpect后置通知获取返回结果 spring 后置处理器_自定义,第1张

在完成各种Aware的设置之后,先执行了BeanPostProcessor的postProcessBeforeInitialization方法,即,初始化前。而在调用初始化方法之后,调用postProcessAfterInitialization方法。

Spring是如何使用的

前面说到上下文注册了BeanFactoryPostProcessor和BeanPostProcessor,那么都有谁呢?

  • AutowiredAnnotationBeanPostProcessor:自动属性注入的,工作在实例化之后,将上下文找到可能的属性设置到bean中。
  • CommonAnnotationBeanPostProcessor:处理@PostConstruct等注解的方法调用
  • PersistenceAnnotationBeanPostProcessor:处理JPA的@PersistenceUnit等注解的

到这里,你可能会好奇,代理是通过什么织入的?代理不是IOC容器的默认功能,是需要我们自己引入aop的相关依赖并且开启注解的。

但还是告诉大家,代理也是通过BeanPostProcessor来实现的。他就是AnnotationAwareAspectJAutoProxyCreator。而他实现了Ordered接口,确保是最后一个执行的,避免重复织入代理。

对于我们自己使用的话,可以参考Spring的用法,定义注解/接口,在后置处理器里面调用。又或者,修改bean的属性值。等等。

总结

我们看源码重点之一是学习人家的设计思路。Spring这套的设计,体现了众多编码原则,例如:

  1. 开闭原则:通过各种各级钩子,对外/为将来提供拓展的可能,而不需要修改本身的类。
  2. 单一职责:通过定义各司其职的处理器,不要给我越权了。各自职责泾渭分明,边界明确。
  3. 接口隔离原则:对处理器进行拆解,抽象出来BeanFactoryPostProcessor和BeanPostProcessor,并界定边界。这个在ApplicationContext接口中的体现尤为明显。

但我最佩服的是Spring能够把如此庞大的一个设计,整的如此整体而统一,在保证拓展性的同时,还能如此井然有序,不带一点凌乱。确实牛啊!



https://www.xamrdz.com/lan/54m1923082.html

相关文章: