spring bean 生命周期
bean 的创建过程
-
读取配置文件,解析配置文件,得到 bean 定义集合
- 每个 bean 的配置都对应一个 BeanDefinition 对象,统一放在容器的 beanFactory.beanDefinitionMap 中,是一个 map
-
bean 工厂后置处理器 BeanFactoryPostProcessor
- 与其说 bean 工厂后置处理器还不如说是 bean定义 后置处理器,因为这时可以修改 BeanDefinition
- 作用是可以修改 BeanDefinition 从而达到修改 bean 的目的
- 也可以往 beanDefinitionMap 增加一个 BeanDefinition ,可以达到不用显示配置 bean 的目的,动态配置 bean
- 如果单纯只是想增加一个 BeanDefinition,可以使用子接口 BeanDefinitionRegistryPostProcessor 来完成
- spring bean 的扩展点之一
-
创建对象
-
根据 BeanDefinition 反射创建 java 对象,此时还不是 bean,或者说还不是完整的 bean
-
创建方式有无参构造、有参构造、工厂方式。都是利用反射来创建对象
-
这个对象会先放入三级缓存,这里只是提一下,后面说 spring 怎么利用三级缓存来处理循环依赖
-
-
属性赋值
- 创建了对象,就该为属性赋值了,分为普通属性和引用了别的 bean 的属性
- 普通属性用 @Value。引用其他 bean 用 @Autowired 或 @Resource 完成赋值,DI 的体现
- 引用其他 bean 的时候,先到一级缓存中找,如果没有再到二级缓存中找,然后是三级缓存,如果都没有,先创建其他 bean
- 如果三级找到了其他 bean,把其他 bean 放入二级缓存,移除三级缓存
- 这个流程先假设没有循环依赖,不然就要先说循环依赖了
-
Aware 回调方法
- bean 通过实现一些 Aware 接口,复写接口方法,创建 bean 的时候 spring 会执行这些方法,可以再次完善 bean 的配置
- BeanFactoryAware 能让当前 bean 拿到 BeanFactory 对象,这个对象包罗万象
- ApplicationContextAware 能让 当前 bean 拿到 ApplicationContext 应用上下文对象,比 BeanFactory 的信息更多
-
bean 后置处理器的 before
- bean 实现 BeanPostProcessor 接口,复写 postProcessBeforeInitialization 方法,创建 bean 的时候 spring 会执行这个方法,再次完善 bean 的配置
- BeanFactoryPostProcessor 是修改 BeanDefinition ,BeanPostProcessor 可以修改 bean
- spring bean 的总要扩展点之一
-
initializingBean 接口的方法
- bean 实现 initializingBean 接口,复写 afterPropertiesSet 方法,创建 bean 的时候 spring 会执行这个方法,再次完善 bean 的配置
-
自定义的 init 方法
- 创建 bean 的时候 spring 会自动执行指定的 init 方法,再次完善 bean 的配置
-
bean后置处理器的 after 方法
- BeanPostProcessor 有两个方法,一个是后置,一个是前置
- 这里是最后节点所以这个方法在扩展时用的最多
-
配置自定义的销毁方法
-
此时 bean 就完整了,放到 单例池,并删除二三级缓存
简言之就是先创建 bean 定义对象,然后根据定义创建 java 对象,属性赋值,然后根据各种回调或接口完善对象,使其成为完整的 bean,最后放入单例池
@Component(value = "testBean") // bean 定义:id = testBean,class = com.yunxi.dg.base.center.trade.demand.engine.statemachine.Test
@Scope(value = "singleton") // bean 定义:scope = singleton
@Lazy(value = false) // bean 定义:不延迟加载
public class Test implements ApplicationContextAware, BeanNameAware, InitializingBean, BeanFactoryPostProcessor, BeanPostProcessor {
private String username;
private int age;
private String sex;
private String addr;
/**
* 虽然类上定义的作用域是单例,但是这里通过修改 beanDefinition 使作用域变为了原型
* 这个方法触发的时机是所有 BeanDefinition 都已经收集完成,将要进行 bean 初始化的时候
* @param configurableListableBeanFactory 这是 BeanFactory 的子接口,为了安全不能拿到全部的 BeanDefinition,只能通过条件获取指定的 BeanDefinition
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor,兵工厂后置处理器");
// 这里不止能获取当前 bean 的 BeanDefinition,可以修改任意 BeanDefinitio
configurableListableBeanFactory.getBeanDefinition("testBean").setScope("property");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware回调");
}
@Override
public void setBeanName(String s) {
System.out.println("BeanNameAware回调");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 修改 bean 的 username
if(bean instanceof Test){
System.out.println("BeanPostProcessor.before");
Test testBean = (Test) bean;
testBean.username = "张三";
return testBean;
}
return bean;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean");
this.sex = "男";
}
@PostConstruct
private void init(){
System.out.println("自定义init方法");
this.addr = "四川成都成华区东丽街";
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof Test){
System.out.println("BeanPostProcessor.after");
// 修改 bean 的 age
Test testBean = (Test) bean;
testBean.age = 18;
return testBean;
}
return bean;
}
}
bean 的生命周期
- 实例化(Instantiation):
- 当 Spring 容器接收到对 Bean 的请求时,首先会进行 Bean 的实例化。这个阶段的实质是通过构造函数或者工厂方法创建 Bean 的实例。
- 依赖注入(Dependency Injection):
- 在实例化后,Spring 开始进行依赖注入。这包括设置 Bean 的属性值、调用 Bean 的
setters
方法来传递依赖,以及通过构造函数注入或者字段注入来完成 Bean 的配置。
- 在实例化后,Spring 开始进行依赖注入。这包括设置 Bean 的属性值、调用 Bean 的
- 初始化前回调(Initialization Callbacks):
- 在依赖注入完成后,Spring 会调用 Bean 实现的
InitializingBean
接口的afterPropertiesSet()
方法,或者使用@PostConstruct
注解标注的方法,来执行一些初始化操作。
- 在依赖注入完成后,Spring 会调用 Bean 实现的
- 自定义初始化方法(Custom Init Method):
- 如果 Bean 配置中指定了自定义的初始化方法(通过 XML 配置或者
@Bean(initMethod="customInit")
),Spring 会调用这个方法来执行额外的初始化逻辑。
- 如果 Bean 配置中指定了自定义的初始化方法(通过 XML 配置或者
- Bean 可用(Bean is ready for use):
- 此时,Bean 已经被完全初始化,可以被应用程序使用。
- 销毁前回调(Destruction Callbacks):
- 当容器关闭时,Spring 会调用实现
DisposableBean
接口的destroy()
方法,或者使用@PreDestroy
注解标注的方法,来执行 Bean 的清理工作和资源释放。
- 当容器关闭时,Spring 会调用实现
- 自定义销毁方法(Custom Destroy Method):
- 如果 Bean 配置中指定了自定义的销毁方法(通过 XML 配置或者
@Bean(destroyMethod="customDestroy")
),Spring 会在容器关闭时调用这个方法来执行额外的清理逻辑。
- 如果 Bean 配置中指定了自定义的销毁方法(通过 XML 配置或者
- 销毁(Destruction):
- 最后,Spring 容器销毁 Bean 的实例,释放它占用的资源。