Spring之Bean(2)循环依赖|初始化|销毁

237 阅读4分钟

Bean生命周期

image-20220106161842735.png 讲解循环依赖之前,我们先看看常说的三级缓存和一部分关键代码,帮助后面理解

//一级缓存
/** 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相互依赖,简化初始化流程图如下: image-20220110173324179.png 循环依赖过程中,三级缓存的变化过程

image-20211224000744223.png bean初始化过程中存放缓存的顺序是3级-->2级-->1级,添加到上一级缓存后就就将下一级的删掉

singletonFactories作用

完成实例化后会在singletonFactories添加一份缓存键为beanName,值为ObjectFactory的函数接口: AbstractAutowireCapableBeanFactory::getEarlyBeanReference。在循环依赖中讲到,当userB进入populateBean阶段进行userA依赖注入,再次进入getBean流程时,会进入第三级缓存获取值userA的值,此时触发getEarlyBeanReference获取userA,若UserA存在代理,则UserA的targetBean会变成proxyBean返给userB,验证如下

image-20220110172909958.png 普通的UserA@2945变成了代理UserA@3fbfa96,此时注入到UserB中的userA为一个代理bean,若UserB本身也被代理了,那userB是在哪儿变成代理bean的呢,验证如下

image-20220110174316649.png 就在初始化的最后一步: AbstractAutowireCapableBeanFactory::applyBeanPostProcessorsAfterInitialization,由AnnotationAwareAspectJAutoProxyCreator类完成代理对象创建,在上面的第三级缓存中也是由此类处理

初始化(initialize)

image-20220106165611108.png 从图中可以看出,对常用的初始化方法中的顺序为ApplicationContextAware::setApplicationContext > @PostConstruct > InitializingBean::afterPropertiesSet > @Bean(initMethod="func")

销毁

在initialize阶段完成后,会给每个bean设置一个销毁适配器

image-20220106180337407.png 这里的映射关系存储在DefaultSingletonBeanRegistry的Map<String, Object> disposableBeans中,DisposableBeanAdapter实现自DisposableBean,并拥有bean和CommonAnnotationBeanPostProcessor的引用,所以在销毁时适配器的destroy方法进行了增强

image-20220106182043228.png

代码示例

@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(销毁)

  1. 实例化

    该阶段完成会向第三级缓存singletonFactories中存放<beanName,ObjectFactory>的键值对,用于后面bean被其他对象引用时生成代理对象

  2. 填值

    实例化完成后对注入的成员变量进行填值,此时又进入getBean流程,返回存在的bean或创建bean

  3. 初始化

    填值完成后进入初始化流程,初始化流程分为4个大的步骤。

    1. 调用通知方法:invokeAwareMethods,主要是通知beanName,BeanFactory
    2. 初始化前bean增强:applyBeanPostProcessorsBeforeInitialization,在此阶段会调用很多processor,常见的会调用ApplicationContextAwareProcessor通知上下文、CommonAnnotationBeanPostProcessor处理PostConstruct注解
    3. 调用自定义初始化函数:调用InitializingBean的afterPropertiesSet,调用@Bean标注的initMethod
    4. 初始化后bean增强:applyBeanPostProcessorsAfterInitialization,在此阶段会调用很多processor,常见的会调用AnnotationAwareAspectJAutoProxyCreator/InfrastructureAdvisorAutoProxyCreator将bean变为proxyBean,这也是前面第三级缓存获取bean进行处理的类
  4. 销毁

    初始化完后会为每个bean设置一个DisposableBeanAdapter销毁适配器,该适配器实现自DisposableBean,并拥有当前实例和CommonAnnotationBeanPostProcessor的引用。若上下问注册过shutdownhook,在程序关闭时会进入bean的摧毁阶段,先调用@PreDestroy注解标注的函数,再调用DisposableBean的destroy接口,最后调用@Bean注解标注的destroyMethod