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(开启某项功能)

  1. 创建一个selector

    1
    2
    3
    4
    5
    6
    7
    public class KImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    System.out.println("ImportSelector");
    return new String[]{KImportService.class.getName()};
    }
    }
  2. 提供一个注解,有此注解就通过@Import引入这个selector

    1
    2
    3
    4
    @Retention(RetentionPolicy.RUNTIME)
    @Import(KImportSelector.class)
    public @interface EnableKImportSelector {
    }
  3. 然后在@COnfiguration中引入注解即可

    1
    2
    3
    4
    5
    @Configuration
    @EnableKImportSelector
    public class BootConfig {

    }

这样,spring就会在启动的时候自动把KImportService加入到容器中

通过这种方式,就可以建立注解功能,没有此注解的就不开启对应的功能

springboot的启动注解@SpringBootApplication注解子注解EnableAutoConfiguration通过@Import加载的AutoConfigurationImportSelector就是ImportSelector的实现

2.2. ImportBeanDefinitionRegistrar

2.2.1. 定义

ImportBeanDefinitionRegistrarImportSelector一样,也是通过@Import注解引入,注入某个beanDefinition
在spring开始加载Beandefinition的时候就会调用,提供一个注册自定义BeanDifinition的地方,很多框架就是如此使用的

2.2.2. 接口解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 不能通过 @Configuration 注解,此类需要使用@Import注解才能生效
public class KImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 这里可以注册beanDefinition
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("ImportBeanDefinitionRegistrar");
}
}
````

通过在`@Configuration`类上引入或创建一个注解再引入的方式,实现加载

```java
@Configuration
@Import(KImportBeanDefinitionRegistrar.class)
public class BootConfig {

}

通过原信息和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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* registry即为springbean定义的注册类,后续beanDefinition都在于此;
* 可以在此手动注入一个 beanDefinirion,之后实例化的时候会根据注入的beanDefinition实例化对应的bean
* @param registry the bean definition registry used by the application context
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry");
registry.registerBeanDefinition("registryHelloService", new RootBeanDefinition(RegistryHelloService.class));

}

/**
* 详见 BeanFactoryPostProcessor,
* 但BeanDefinitionRegistryPostProcessor执行先于BeanFactoryPostProcessor执行
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//beanFactory.getBeanDefinition("");
//beanFactory.getBean("");
System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory");
}
}

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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 需要注入到容器中
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* 在标准初始化之后修改应用程序上下文的内部bean工厂。所有的bean定义都已加载,但还没有实例化任何bean。
* 这允许覆盖或添加BeanDefinition属性。
* @param beanFactory the bean factory used by the application context
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory");

//修改属性
BeanDefinition bd = beanFactory.getBeanDefinition("beanFactoryPostService");
MutablePropertyValues pvs = bd.getPropertyValues();
pvs.addPropertyValue("name","name haha ");

//配置自动Bean注入
//此时可以将autowirdMode设置为 1或2 ,通过对应的set方法自动注入对应的bean,如果没有对应方法依然为空。
AbstractBeanDefinition abd = (AbstractBeanDefinition)beanFactory.getBeanDefinition("beanFactoryPostService");
abd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}

2.4.3. xml配置类(暂不考虑)

一般情况下我们是不会主动去自定义 BeanFactoryPostProcessor,其实 Spring 为我们提供了几个常用的BeanFactoryPostProcessor,他们是PropertyPlaceholderConfigurerPropertyOverrideConfigurer

PropertyPlaceholderConfigurer 允许我们在 XML 配置文件中使用占位符并将这些占位符所代表的资源单独配置到简单的 properties 文件中来加载,
PropertyOverrideConfigurer 则允许我们使用占位符来明确表明bean 定义中的 property 与 properties 文件中的各配置项之间的对应关系,这两个类在我们大型项目中有非常重要的作用。

2.5. FactoryBean<T>

配置中配置FactoryBean,实现FactoryBean的配置不会直接注入自己,会在bean初始化时getBean()中获取其getObject()方法,并且加入上下文缓存中,这样可在获取时自定义实例化的数据

FactoryBean是在BeanFactory循环初始化单例bean的时候调用,会单独判断是否为FactoryBean类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class MyFactoryBean implements FactoryBean<FactoryBeanService> {

/**
* 在初始化bean的时候才真正调用此方法,可以自定义bean的生成逻辑
* @return
* @throws Exception
*/
@Override
public FactoryBeanService getObject() throws Exception {
FactoryBeanService service = new FactoryBeanService();
service.setName("FactoryBean name");
return service;
}

@Override
public Class<?> getObjectType() {
return FactoryBeanService.class;
}
}

3. Bean初始化增强

3.1. BeanPostProcessor

实现BeanPostProcessor的接口首先会在BeanDefinition加载完成后实例化,实例化后其回调方法生效,后续所有的Bean实例化时均会执行其postProcessBeforeInitialization()postProcessAfterInitialization()方法。

每个Bean实例化执行顺序:Aware相关 →→ postProcessBeforeInitialization()→→@PostConstruct →→InitializingBean接口→→postProcessAfterInitialization()DisposableBean接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**每个bean初始化的时候都会调用此类,比如可以用此类接收到所有的注册到容器中的bean
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 在bean初始化完成前, `Aware` 对应执行完成后执行此方法
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}

/**
* 在bean初始化完成后,`InitializingBean`完成后执行方法
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}

3.2. BeanFactoryAware

实现Beanfactory接口,可以拿到BeanFactory

1
2
3
4
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}

3.3. ApplicationContextAware

实现ApplicationContextAware可以拿到上下文

1
2
3
4
5
public interface ApplicationContextAware extends Aware {

void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

3.4. @PostConstruct

添加注解的方法会在执行InitializingBean之前执行初始化方法,相当于xml配置中的init-method标签方法

PostConstruct方法的执行也是一个特殊的BeanPostProcessorInitDestroyAnnotationBeanPostProcessor来完成,执行before()方法时会调用PostConstruct的方法执行,而after方法则不处理直接返回

1
2
3
4
@PostConstruct
private void init(){
System.out.println("执行 @PostConstruct");
}

3.5. InitializingBean

实现InitializingBean 可以在Bean初始化完成时执行afterPropertiesSet()方法做后续处理

1
2
3
4
5
public interface InitializingBean {

void afterPropertiesSet() throws Exception;

}

3.6. DisposableBean

实现DisposableBean 可以在Bean销毁时执行destroy()销毁方法,一般也用不到

1
2
3
4
5
public interface DisposableBean {

void destroy() throws Exception;

}

3.7. ObjectProvider<T> provider构造器注入

构造器注入时注入ObjectProvider,可以注入类的集合或类,可以根据传参选择构造器或者在注入列表中选择一个合适的实例。当实例不存在时注入也不会报错。

1
2
3
4
5
6
7
8
9
10
11
12
@Service
public class MyObjectProviderService {
FactoryBeanService factoryBeanService;
List<FactoryBeanService> factoryBeanServices;

public MyObjectProviderService(ObjectProvider<FactoryBeanService> factoryBeanService) {
//注入集合,没有也不会报错,如果是List<FactoryBeanService>传参
this.factoryBeanServices = factoryBeanService.orderedStream().collect(Collectors.toList());
//注入单个
this.factoryBeanService = factoryBeanService.getIfAvailable();
}
}

4. 总结

按照生命周期顺序,扩展函数为
ImportSelector / DeferredImportSelector
ImportBeanDefinitionRegistrar
BeanDefinitionRegistryPostProcessor
BeanFactoryPostProcessor
FactoryBean<T> #getObject
BeanPostProcessor
BeanNamedAware
EnviromentAware
BeanFactoryAware
ApplicationContextAware
@PostConstruct
InitializingBean
DisposableBean
ObjectProvider<T> provider 构造器注入