Spring 为开发者预留了很多容器的扩展点,本文记录一下几个常用的扩展点的相关知识。
BeanFactoryPostProcessor
BeanFactoryPostProcessor
可以对 Bean 配置元信息进行操作,也就是说可以读取 BeanDefinition
,并在 Bean 实例化之前进行修改。具体逻辑在下图的 3-5-1
中。
BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor
作为 BeanFactoryPostProcessor
的子接口额外提供了 postProcessBeanDefinitionRegistry
方法。
方法执行顺序
具体逻辑在 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
方法中。
FactoryBean
FactoryBean
主要用来定制化 Bean 的创建逻辑,提供了三个方法:
Object getObject()
:返回FactoryBean
所创建的对象。boolean isSingleton()
:返回FactoryBean
所创建的对象是否为单例,默认返回 true。Class getObjectType()
:返回FactoryBean
所创建的对象的类型,如果我们能确认返回对象的类型的话,应该对该方法做出正确的实现,而不是返回 null。
注意点
- 通过 FactoryBean.getBean(factoryBeanName) 方法返回的不是
FactoryBean
实例,而是getObject()
方法创建的对象。想要获得FactoryBean
实例需要在 factoryBeanName 前加&
符号。 SmartFactoryBean
是FactoryBean
的子接口,额外提供了boolean isPrototype()
和boolean isEagerInit()
方法,默认都是返回false
。可以通过实现该接口并重写isEagerInit
方法返回true
达到在 Spring 容器启动时就执行getObject
方法创建 Bean 的目的。
如何将一个对象交由 Spring 管理
Aware 接口
所有的 Aware
接口都是为了能让我们拿到容器中相关的资源,比如 BeanNameAware
,可以让我们拿到 Bean 的名称,ApplicationContextAware
可以让我们拿到整个容器。
执行阶段
- 第一阶段,执行
BeanXXXAware
接口;
AbstractAutowireCapableBeanFactory#initializeBean
...
invokeAwareMethods(beanName, bean)
该阶段只有BeanNameAware
,BeanClassLoaderAware
,BeanFactoryAware
这三个接口会被执行。
- 执行其他 Aware 接口
AbstractAutowireCapableBeanFactory#initializeBean
...
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
该阶段会执行其他 Aware 接口,不过是通过专门的后置处理器进行处理。例如 ApplicationContextAware
接口会被 ApplicationContextAwareProcessor
处理。并且这一步还会通过 CommonAnnotationBeanPostProcessor
后置处理器完成对 @PostConstructor
注解的处理, 注意 @PreDestroy
@Resource
也是通过 CommonAnnotationBeanPostProcessor
处理的。
LifeCycle
LifeCycle
顾名思义是一个生命周期,Spring 容器通过组合的方式持有一个 LifeCycleProcessor
实例,在容器启动和关闭的时候会回调当前容器中所有 LifeCycle
实例的 start
和 stop
方法,其中 stop
方法只有在 isRunning
方法返回 true 的前提下才会生效。
AbstractApplicationContext#refresh
...
finishRefresh()
...
initLifecycleProcessor();
getLifecycleProcessor().onRefresh();
具有依赖关系的 Bean 之间,例如 A 依赖了 B,那么 B.start 方法先于 A.start 执行,B.stop 方法晚于 A.stop 执行。
如果没有依赖关系的 Bean 之间要如何控制方法执行的先后顺序呢,可以通过继承 SmartLifeCycle
重写 getPhase()
方法,返回值越小 start 方法就越先执行,对应的 stop 方法就越晚执行。