一、Bean
Bean创建过程
Spring bean到底是如何创建的?(上) (qq.com)
1. BeanDefinition读取注册
Spring容器启动时,先按照声明bean的方式(注解、xml等)去读取所有bean的配置信息(类名,是否单例,初始化方法名称等),然后将这些BD存放一个在map中。在DefaultListableBeanFactory
类中。
通过注解扫描出来的Bean的BeanDefinition用
ScannedGenericBeanDefinition
来表示。
配置类的BeanDefinition用AnnotatedGenericBeanDefinition
来表示。
用@Bean声明的Bean的BeanDefinition用ConfigurationClassBeanDefinition
来表示。
2. 获取Bean&三级缓存防止循环依赖
Spring 循环依赖,三级缓存注入代理对象_spring三级缓存代理对象-优快云博客
三级缓存其实是三个Map
假设A、B存在循环依赖:
@Component
public class A {
@Resource
private B b;
}
@Component
public class B {
@Resource
private A a;
}
-
首先对
a
这个bean调用AbstractBeanFactory#doGetBean()
,会先尝试从三级缓存中获取。 -
获取失败,调用
getSingleton()
方法。然后调用createBean() --> doCreateBean
对该Bean进行实例化、属性注入、初始化等。- 实例化:通过反射创建一个A对象,放入第三级缓存中(
singletonFactories
)。 - 属性注入:对这个对象进行属性依赖的注入,发现需要名为b的Bean,再次调用
doGetBean() --> getSingleton()
发现三级缓存中均不存在b,于是开始创建b。 b
的创建过程和a
一样,只不过在属性注入的时候发现a
存在第三级缓存中,成功注入了a
,并且将a
放到第二级缓存,b
成功创建。- a进行初始化
- 实例化:通过反射创建一个A对象,放入第三级缓存中(
-
a
,b
均创建完成。
3. doCreateBean过程
在AbstractAutowireCapableBeanFactory
类中,使用了doCreateBean()
方法创建Bean。
主要干三件事情:
- 反射实例化 bean 对象:
createBeanInstance()
- 属性注入:
populateBean()
- 初始化 bean 对象:
initializeBean()
Bean的生命周期
Bean的生命周期也就是从doCreateBean()
开始
五步骤版本
五步骤版本:
1. 实例化
2. 依赖注入
3. 初始化
4. 使用Bean
5. 销毁Bean
- 实例化:调用构造方法,或者是使用工厂模式构造bean
<!--第一种方式-->
<bean id="bean1" class="demo3.Bean1"></bean>
<!--第二种方式:静态工厂,调用工厂中静态方法-->
<bean id="bean2" class="demo3.Bean2Factory" factory-method="getBean2"></bean>
<!--第三种方式:动态工厂,调用内部方法-->
<bean id="bean3Factory" class="demo3.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
</beans>
-
依赖注入:对Setter或者@Resource标注的属性进行赋值。spring.xml中对setter赋值。
-
初始化:自定义了初始化方法并且在
init-method
中指定,可实现如数据库初始连接等操作。
<bean id="dog" class="com.example.springbeanlife.bean.Dog" init-method="myInit" destroy-method="myDestroy">
<property name="name" value="小狗"/>
</bean>
- 销毁:调用了
容器.close()
或关闭程序后,会调用在destroy-method
中指定的销毁方法。
七步骤版本
增加一个BeanPostProcessor
七步骤版本:
1. 实例化
2. 依赖注入
3. 初始化前 BeanPostProcessor before方法
4. 初始化
5. 初始化后 BeanPostProcessor after方法
6. 使用Bean
7. 销毁Bean
实现BeanPostProcessor
接口
public class MyProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("dog".equals(beanName)){
System.out.println("3. 初始化前 BeanPostProcessor before方法");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("dog".equals(beanName)){
System.out.println("5. 初始化后 BeanPostProcessor after方法");
}
return bean;
}
}
注册BeanPostProcessor
为Bean。BeanPostProcessor
的执行顺序与注册到Spring的顺序有关。
<!--先执行processor再执行processor2-->
<bean id="processor" class="com.example.springbeanlife.bean.MyProcessor"/>
<bean id="processor2" class="com.example.springbeanlife.bean.MyProcessor2"/>
十步骤版本
增加三个接口
十步骤版本:
----实例化----
1. 实例化
----依赖注入---
2. 依赖注入
----初始化----
※3. BeanNameAware BeanFactoryAware 方法
4. 初始化前 BeanPostProcessor before方法
※5. InitializingBean接口方法
6. 初始化
7. 初始化后 BeanPostProcessor after方法
----使用----
8. 使用Bean
----销毁----
※9. DisposableBean接口方法执行
10. 销毁Bean
-
XXXAware:通常Aware有这样一个规则:Aware接口的名称,表示依赖对象的类名称。
例如,一个bean需要使用ApplicationContext
,实现ApplicationContextAware
接口即可。 -
InitializingBean:实现一个
afterPropertiesSet()
初始化方法 -
DisposableBean:实现销毁方法。bean初始化后,会被放入disposableBeans的Map集合中,spring关闭时会发布事件,调用
lifecycleProcessor.onClose()
,循环遍历这个Map,逐个执行销毁方法,可用于释放资源等。
二、BeanPostProcessor
可看看上个标题Bean的生命周期中有提到,BeanPostProcessor
是在Bean初始化前后增加方法的。
如何触发before和after方法的呢?
Spring会在某个Bean初始化过程之前&之后(环绕初始化方法)会针对该对象分别调用所有BeanPostProcessor
对象的方法。
BeanPostProcessor
接口实现如下(AOP就是将原本Bean对象包装成代理类然后return)
public class MyProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("dog".equals(beanName)){
System.out.println("3. 初始化前 BeanPostProcessor before方法");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("dog".equals(beanName)){
System.out.println("5. 初始化后 BeanPostProcessor after方法");
}
return bean;
}
}
对两个方法打断点查看调用栈后进入了initializeBean(),如图:
-
Aware:
invokeAwareMethods()
方法调用该Bean实现的所有Aware接口 -
Before:
applyBeanPostProcessorsBeforeInitialization
即是调用所有BeanPostProcessor
的postProcessBeforeInitialization
方法。(接下来进入这个方法源码中) -
初始化:
invokeInitMethods
调用该Bean的所有初始化方法,包括注册的init-method
或者实现InitializingBean
接口的方法。 -
After:
applyBeanPostProcessorsAfterInitialization
即是调用所有BeanPostProcessor
的postProcessAfterInitialization
方法
如图,getBeanPostProcessors()
获取当前所有的BeanPostProcessors
对象,并且对当前Bean循环调用它们的Before方法。
BeanPostProcessors
的执行顺序与其注册到Spring的顺序有关。
<bean id="processor2" class="com.example.springbeanlife.bean.MyProcessor2"/>
<bean id="processor" class="com.example.springbeanlife.bean.MyProcessor"/>
三、 AOP代理对象是怎么创建的?
BeanPostProcessor —— 连接Spring IOC和AOP的桥梁 - 知乎 (zhihu.com)
利用BPP,在before或after方法中对对象进行判断,查看该对象是否需要切面操作,如果需要的话就会生成该对象的代理对象并返回装配到bean中。
具体代码是在AbstractAutoProxyCreator
类中实现的postProcessAfterInitialization