Bean生命周期
讲解循环依赖之前,我们先看看常说的三级缓存和一部分关键代码,帮助后面理解
//一级缓存
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二级缓存
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
//三级缓存
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
假设UserA与UserB相互依赖,简化初始化流程图如下:
循环依赖过程中,三级缓存的变化过程
bean初始化过程中存放缓存的顺序是3级-->2级-->1级,添加到上一级缓存后就就将下一级的删掉
singletonFactories作用
完成实例化后会在singletonFactories添加一份缓存键为beanName,值为ObjectFactory的函数接口: AbstractAutowireCapableBeanFactory::getEarlyBeanReference。在循环依赖中讲到,当userB进入populateBean阶段进行userA依赖注入,再次进入getBean流程时,会进入第三级缓存获取值userA的值,此时触发getEarlyBeanReference获取userA,若UserA存在代理,则UserA的targetBean会变成proxyBean返给userB,验证如下
普通的UserA@2945变成了代理UserA@3fbfa96,此时注入到UserB中的userA为一个代理bean,若UserB本身也被代理了,那userB是在哪儿变成代理bean的呢,验证如下
就在初始化的最后一步:
AbstractAutowireCapableBeanFactory::applyBeanPostProcessorsAfterInitialization,由AnnotationAwareAspectJAutoProxyCreator类完成代理对象创建,在上面的第三级缓存中也是由此类处理
初始化(initialize)
从图中可以看出,对常用的初始化方法中的顺序为ApplicationContextAware::setApplicationContext > @PostConstruct > InitializingBean::afterPropertiesSet > @Bean(initMethod="func")
销毁
在initialize阶段完成后,会给每个bean设置一个销毁适配器
这里的映射关系存储在DefaultSingletonBeanRegistry的Map<String, Object> disposableBeans中,DisposableBeanAdapter实现自DisposableBean,并拥有bean和CommonAnnotationBeanPostProcessor的引用,所以在销毁时适配器的destroy方法进行了增强
代码示例
@Configuration
@ComponentScan(basePackages = "com.jm.demo.demo1")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
public UserA userA(){
return new UserA();
}
@Bean
public UserB userB(){
return new UserB();
}
}
@Aspect
@Component
public class F1AspectJ {
@Before("execution(* com.jm.demo.demo1.User.f1(..))")
public void haha(){
System.out.println("这里有个切面");
}
}
public interface User {
void f1();
}
public class UserA implements User, InitializingBean, ApplicationContextAware, DisposableBean {
private int order = 0;
@Autowired
private UserB userB;
public UserA() {
System.out.println("constructor order:" + order++);
}
@PostConstruct
public void postConstruct() {
System.out.println("postContruct order:" + order++);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean order:" + order++);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware order:" + order++);
}
public void initMethod() {
System.out.println("initMethod..." + order++);
}
public void destroyMethod() {
System.out.println("destroyMethod..." + order++);
}
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy..." + order++);
}
@Override
public void destroy() throws Exception {
System.out.println("destroy..." + order++);
}
@Override
public void f1() {
System.out.println("userA f1...");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
context.registerShutdownHook();
UserA userA = context.getBean("userA", UserA.class);
userA.f1();
UserB userB = context.getBean("userB", UserB.class);
userB.f1();
}
}
public class UserB implements User{
@Autowired
private UserA userA;
public UserB(){
System.out.println("UserB...");
}
@Override
public void f1() {
System.out.println("userB f1...");
}
}
总结
Bean生命周期包括:instantiate(实例化)、populate(填值)、initialize(初始化)、destroy(销毁)
-
实例化
该阶段完成会向第三级缓存singletonFactories中存放<beanName,ObjectFactory>的键值对,用于后面bean被其他对象引用时生成代理对象
-
填值
实例化完成后对注入的成员变量进行填值,此时又进入getBean流程,返回存在的bean或创建bean
-
初始化
填值完成后进入初始化流程,初始化流程分为4个大的步骤。
- 调用通知方法:invokeAwareMethods,主要是通知beanName,BeanFactory
- 初始化前bean增强:applyBeanPostProcessorsBeforeInitialization,在此阶段会调用很多processor,常见的会调用ApplicationContextAwareProcessor通知上下文、CommonAnnotationBeanPostProcessor处理PostConstruct注解
- 调用自定义初始化函数:调用InitializingBean的afterPropertiesSet,调用@Bean标注的initMethod
- 初始化后bean增强:applyBeanPostProcessorsAfterInitialization,在此阶段会调用很多processor,常见的会调用AnnotationAwareAspectJAutoProxyCreator/InfrastructureAdvisorAutoProxyCreator将bean变为proxyBean,这也是前面第三级缓存获取bean进行处理的类
-
销毁
初始化完后会为每个bean设置一个DisposableBeanAdapter销毁适配器,该适配器实现自DisposableBean,并拥有当前实例和CommonAnnotationBeanPostProcessor的引用。若上下问注册过shutdownhook,在程序关闭时会进入bean的摧毁阶段,先调用@PreDestroy注解标注的函数,再调用DisposableBean的destroy接口,最后调用@Bean注解标注的destroyMethod