文章目录
1 简述
在spring环境下bean的生命周期大致可以分为下面三种情况:
(1)多实例,bean的创建、初始化在bean被使用的时候,bean的销毁由JVM的垃圾回收器进行处理。
(2)单实例懒加载的bean(注意
:懒加载一般指的是单实例bean):创建、初始化在bean第一次被使用的时候,之后便和单实例bean一样了,销毁在IOC容器关闭的时候。
(3)单实例bean:bean的创建、初始化在项目启动时,销毁在IOC容器关闭时。
本文主要来剖析单实例bean的创建+初始化过程。
2 源码解析之主干分析
感觉自己写博客也有一段时间了,现在回过头来看自己原来关于源码解读的文章,很多我自己都看不下去,感觉就是干巴巴的一行行的解读源码,但是回过头却很难一下就抓住整个代码的主干
,所以这次我打算换种方式来写这篇文章。
跟踪源码发现,在spring中单实例bean真正创建+初始化的骨架
被封装在了AbstractAutowireCapableBeanFactory类的doCreateBean方法里。在该方法里主要包含如下三个方法:
3 源码解析之详细解读
下面将对doCreateBean中的三个主要方法做进一步地解析。
3.1 bean的创建 — Instantiate the bean
// Instantiate the bean.
createBeanInstance(beanName, mbd, args); // 源码538行
对于使用@Component注入IOC容器的对象来说就是new当前对象
对于使用@Bean注入的对象来说会走@Bean注解指定的方法来new当前对象—>当然可以在这里向当前对象里set一些属性,如:
@Bean(name = "cat")
public Cat buildCat() {
Cat cat = new Cat();
cat.setName("花花"); //为bean设置一些属性
return cat;
}
注意:
但是通过@Autowired注入的属性不会在这一步进行注入。
3.2 bean的初始化 — Initialize the bean instance
包括如下两步:
// Initialize the bean instance.
populateBean(beanName, mbd, instanceWrapper); // 源码575行
exposedObject = initializeBean(beanName, exposedObject, mbd); // 源码576行
3.2.1 populateBean(beanName, mbd, instanceWrapper)
@Autowired注入属性的逻辑在该方法里执行。— 我觉得
这里应该是依赖注入的精髓。
这块代码的逻辑大致如下:
(1)假如当前bean里要@Autowired的属性在IOC容器里已经存在了,即这个属性先于当前bean被注入到了IOC容器 —> spring会在populateBean方法的具体实现里直接将该属性设置到当前bean里—>从而完成属性的注入。
(2)但是假如当前bean里要@Autowired的属性还没被注入到IOC容器 —> spring会在populateBean方法的具体实现里调用生成要@Autowired的属性对象的方法,让要@Autowired的属性对象先进行创建+初始化+注入到IOC容器 —> 然后再将要@Autowired的属性对象注入到当前bean。
总之一句话:在执行完populateBean(beanName, mbd, instanceWrapper)方法,当前bean里要@Autowired的属性已经全部被注入到了当前bean对象里。
3.2.2 initializeBean(beanName, exposedObject, mbd);
这块源码其实我在另一篇文章《【spring】详解InitializingBean、initMethod和@PostConstruct》里进行解读过,这里也将其骨干
给抽出来:
3.2.2.1 applyBeanPostProcessorsBeforeInitialization方法
代码很简单,简单进行一下分析:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获取到所有的BeanPostProcessor,
//并拿着当前bean将所有的processor.postProcessBeforeInitialization方法遛一遍
//如果当前bean满足某个processor.postProcessBeforeInitialization方法的条件,就会执行具体的逻辑
//并返回执行结果后的bean,
//如果没满足的话就在该processor.postProcessBeforeInitialization方法里遛一圈直接返回
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
3.2.2.2 invokeAwareMethods(beanName, bean)方法
就是执行InitializingBean、initMethod或@PostConstruct对应的方法
可以参看我的另一篇文章 — 《【spring】详解InitializingBean、initMethod和@PostConstruct》。
3.2.2.3 applyBeanPostProcessorsAfterInitialization方法
源码如下,几乎和applyBeanPostProcessorsBeforeInitialization的具体实现方法一样,也是获取到所有的BeanPostProcessor ,然后拿着当前bean,将所有的processor.postProcessAfterInitialization方法遛一遍,下面就不多过进行标注了。
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
4 两句话总结
(1)
★★★populateBean(beanName, mbd, instanceWrapper)方法之后, @Autowired相关的属性注入已经全部完成
(2)可以借助initializeBean(beanName, exposedObject, mbd)方法完成bean的额外或者说特殊属性注入,这里又包括三种方式,其实更确切来说是三个时机:
- 前置处理
- 执行InitializingBean、initMethod或@PostConstruct对应的初始化方法
- 后置处理