Spring spring生命周期扩展
1. Bean生命周期 主要扩展钩子函数
生命周期图片
- Bean生命周期主要分为两部分,第一部分为BeanDefinition的构建及初始化,第二部分为Bean的初始化
BeanDefiniton是将bean的相关信息(字段,属性等)封装在一起,实例化初始化bean的时候都在其中获取bean的信息 - Bean生命周期的钩子函数主要顺序
BeanDefinition:ImportSelector,ImportBeanDefinitionRegistrar,BeanDefinitionRegistryPostProcessor->BeanFactoryPostProcessor->FactoryBean->
Bean:BeanPostProcessor->ObjectProvider->BeanFactoryAware->ApplicationContextAware->@PostConstruct->InitializingBean->DisposableBean
2. BeanDifinition初始化增强
2.1. ImportSelector
2.1.1. 定义
ImportSelector主要通过AnnotationMetadata返回一个类名,之后spring就会根据类名加入BeanDefinition中了
其作用和@Component差不多,主要不同在于它可以在不需要的地方不加载,多用于框架功能的开关,普通项目用它意义不大,
2.1.2. 接口解析
通过创建一个注解实现是否加载某个bean(开启某项功能)
创建一个selector
1
2
3
4
5
6
7public class KImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("ImportSelector");
return new String[]{KImportService.class.getName()};
}
}提供一个注解,有此注解就通过
@Import引入这个selector1
2
3
4
public EnableKImportSelector {
}然后在
@COnfiguration中引入注解即可1
2
3
4
5
public class BootConfig {
}
这样,spring就会在启动的时候自动把KImportService加入到容器中
通过这种方式,就可以建立注解功能,没有此注解的就不开启对应的功能
springboot的启动注解@SpringBootApplication注解子注解EnableAutoConfiguration通过@Import加载的AutoConfigurationImportSelector就是ImportSelector的实现
2.2. ImportBeanDefinitionRegistrar
2.2.1. 定义
ImportBeanDefinitionRegistrar 同ImportSelector一样,也是通过@Import注解引入,注入某个beanDefinition
在spring开始加载Beandefinition的时候就会调用,提供一个注册自定义BeanDifinition的地方,很多框架就是如此使用的
2.2.2. 接口解析
1 | // 不能通过 @Configuration 注解,此类需要使用@Import注解才能生效 |
通过原信息和registry注册
2.3. BeanDefinitionRegistryPostProcessor
2.3.1. 定义
BeanDefinitionRegistryPostProcessor是用于在Spring的IoC容器即将开始后置处理BeanDefinition之前,提供一个扩展点让我们可以手动往Spring的IoC容器中注册自定义的BeanDefinition。
在Spring的工作流程中,它的执行顺序比BeanFactoryPostProcessor还要早。这是因为BeanDefinitionRegistryPostProcessor接口是继承自BeanFactoryPostProcessor的,它添加了一个新的方法postProcessBeanDefinitionRegistry()。这个方法在所有的bean定义将要被加载,bean工厂将要被初始化,但此时后处理器尚未处理之前调用。
这就意味着,这个接口的主要用途是在正常的Spring自动扫描注册过程之前或之后,提供一种手动添加bean定义或者更改bean定义的机制。
这对于想要动态注入bean的场景非常有用,例如你可以根据不同的配置文件,向Spring容器动态地注入不同的bean。
2.3.2. 接口解析
1 |
|
2.4. BeanFactoryPostProcessor
2.4.1. BeanFactoryPostProcessor定义
在 Spring 容器启动阶段,Spring 也提供了一种容器扩展机制:BeanFactoryPostProcessor,该机制作用于容器启动阶段,允许我们在容器实例化 Bean 之前对注册到该容器的 BeanDefinition 做出修改。
implements BeanFactoryPostProcessor 的接口在BeanDifinition加载完成后、在Bean初始化之前执行操作,主要操作beanDifinition的相关东西,修改BeanDifinition的相关属性
注意: 在 #postProcessBeanFactory(...) 方法中,千万不能进行 Bean 的实例化工作,因为这样会导致 Bean 过早实例化,会产生严重后果,我们始终需要注意的是 BeanFactoryPostProcessor 是与 BeanDefinition 打交道的,如果想要与 Bean 打交道,请使用 BeanPostProcessor 。
BeanFactoryPostProcessor支持排序,一个容器可以同时拥有多个 BeanFactoryPostProcessor ,这个时候如果我们比较在乎他们的顺序的话,可以实现 Ordered接口。
2.4.2. BeanFactoryPostProcessor接口解析
1 | // 需要注入到容器中 |
2.4.3. xml配置类(暂不考虑)
一般情况下我们是不会主动去自定义 BeanFactoryPostProcessor,其实 Spring 为我们提供了几个常用的BeanFactoryPostProcessor,他们是PropertyPlaceholderConfigurer 和 PropertyOverrideConfigurer
PropertyPlaceholderConfigurer 允许我们在 XML 配置文件中使用占位符并将这些占位符所代表的资源单独配置到简单的 properties 文件中来加载,PropertyOverrideConfigurer 则允许我们使用占位符来明确表明bean 定义中的 property 与 properties 文件中的各配置项之间的对应关系,这两个类在我们大型项目中有非常重要的作用。
2.5. FactoryBean<T>
配置中配置FactoryBean,实现FactoryBean的配置不会直接注入自己,会在bean初始化时getBean()中获取其getObject()方法,并且加入上下文缓存中,这样可在获取时自定义实例化的数据
FactoryBean是在BeanFactory循环初始化单例bean的时候调用,会单独判断是否为FactoryBean类型
1 |
|
3. Bean初始化增强
3.1. BeanPostProcessor
实现BeanPostProcessor的接口首先会在BeanDefinition加载完成后实例化,实例化后其回调方法生效,后续所有的Bean实例化时均会执行其postProcessBeforeInitialization()和postProcessAfterInitialization()方法。
每个Bean实例化执行顺序:Aware相关 →→ postProcessBeforeInitialization()→→@PostConstruct →→InitializingBean接口→→postProcessAfterInitialization() →DisposableBean接口
1 | /**每个bean初始化的时候都会调用此类,比如可以用此类接收到所有的注册到容器中的bean |
3.2. BeanFactoryAware
实现Beanfactory接口,可以拿到BeanFactory
1 | public interface BeanFactoryAware extends Aware { |
3.3. ApplicationContextAware
实现ApplicationContextAware可以拿到上下文
1 | public interface ApplicationContextAware extends Aware { |
3.4. @PostConstruct
添加注解的方法会在执行InitializingBean之前执行初始化方法,相当于xml配置中的init-method标签方法
PostConstruct方法的执行也是一个特殊的BeanPostProcessor→InitDestroyAnnotationBeanPostProcessor来完成,执行before()方法时会调用PostConstruct的方法执行,而after方法则不处理直接返回
1 |
|
3.5. InitializingBean
实现InitializingBean 可以在Bean初始化完成时执行afterPropertiesSet()方法做后续处理
1 | public interface InitializingBean { |
3.6. DisposableBean
实现DisposableBean 可以在Bean销毁时执行destroy()销毁方法,一般也用不到
1 | public interface DisposableBean { |
3.7. ObjectProvider<T> provider构造器注入
构造器注入时注入ObjectProvider,可以注入类的集合或类,可以根据传参选择构造器或者在注入列表中选择一个合适的实例。当实例不存在时注入也不会报错。
1 |
|
4. 总结
按照生命周期顺序,扩展函数为ImportSelector / DeferredImportSelectorImportBeanDefinitionRegistrarBeanDefinitionRegistryPostProcessorBeanFactoryPostProcessorFactoryBean<T> #getObjectBeanPostProcessorBeanNamedAwareEnviromentAwareBeanFactoryAwareApplicationContextAware@PostConstructInitializingBeanDisposableBeanObjectProvider<T> provider 构造器注入
