Spring Bean生命周期

Java资料站

共 13726字,需浏览 28分钟

 ·

2021-05-19 02:37

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

  作者 |  歪头儿在帝都 

来源 |  urlify.cn/um6rIv

前言

Spring Bean生命周期是常见的面试题,也是日常开发中经常用到的技术点,在应用开发中,常常需要执行一些特殊的初始化工作,如建立数据库连接,打开网络连接,又比如在一些业务bean里,你想拿到Spring IOC容器,又或者是想拿到一些已经实例化的Bean。同时,在服务结束时,也有一些销毁销毁工作需要执行。为了便于工作的设计,Spring IOC提供相关接口,可以让应用定制Bean的初始化和销毁。

Spring Bean生命周期

先来看一下Spring Bean生命周期流程图,方便对照后续的源码分析。

Spring Bean生命周期从大的节点上分为4个过程:实例化、属性赋值、初始化、销毁。日常业务开发过程中,我们应该涉及最多的两个点就是初始化和销毁,比如自定义Bean实现InitializingBean、DisposeableBean。

源码分析

Spring IOC容器初始化

初始化从AbstractAutowireCapableBeanFactory.doCreateBean方法开始说起,我在对应的代码位置标注了关键点

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
 BeanWrapper instanceWrapper = null;
 if (mbd.isSingleton()) {
  instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
 }
    
 //1. Bean实例化
 if (instanceWrapper == null) {
    instanceWrapper = this.createBeanInstance(beanName, mbd, args);
 }

 Object bean = instanceWrapper.getWrappedInstance();
 Class<?> beanType = instanceWrapper.getWrappedClass();
 if (beanType != NullBean.class) {
  mbd.resolvedTargetType = beanType;
 }

 synchronized(mbd.postProcessingLock) {
  if (!mbd.postProcessed) {
   try {
    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
   } catch (Throwable var17) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
   }

   mbd.postProcessed = true;
  }
 }

 boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
 if (earlySingletonExposure) {
  this.addSingletonFactory(beanName, () -> {
   return this.getEarlyBeanReference(beanName, mbd, bean);
  });
 }

 Object exposedObject = bean;

 try {
     //2.属性赋值
       this.populateBean(beanName, mbd, instanceWrapper);
     //3.初始化
     exposedObject = this.initializeBean(beanName, exposedObject, mbd);
 } catch (Throwable var18) {
     if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
  throw (BeanCreationException)var18;
     }

     throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
 }

 if (earlySingletonExposure) {
  Object earlySingletonReference = this.getSingleton(beanName, false);
  if (earlySingletonReference != null) {
   if (exposedObject == bean) {
    exposedObject = earlySingletonReference;
   } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
    String[] dependentBeans = this.getDependentBeans(beanName);
    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
    String[] var12 = dependentBeans;
    int var13 = dependentBeans.length;

    for(int var14 = 0; var14 < var13; ++var14) {
     String dependentBean = var12[var14];
     if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
      actualDependentBeans.add(dependentBean);
     }
    }

    if (!actualDependentBeans.isEmpty()) {
     throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
    }
   }
  }
 }

 try {
     //4.销毁 - 注册回调接口
     this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
     return exposedObject;
 } catch (BeanDefinitionValidationException var16) {
     throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
 }
}

为了保持代码片段精简,我删掉了其中的logger代码。


从以上代码片段里可以看到我们上面总结的Spring生命后期4个关键点都有体现,我们着重分析初始化和销毁流程。

AbstractAutowireCapableBeanFactory.initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
 //1.检查Aware相关接口并设置相关依赖
    //BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged(() -> {
   this.invokeAwareMethods(beanName, bean);
   return null;
  }, this.getAccessControlContext());
 } else {
  this.invokeAwareMethods(beanName, bean);
 }

    //2.BeanPostProcessor前置处理
 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
     //BeanPostProcessor接口的postProcessBeforeInitialization回调
  wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
 }
    
 //3.若实现InitializingBean接口,则调用afterPropertiesSet()
 //4.若配置自定义的init-method(), 则执行。
 try {
  this.invokeInitMethods(beanName, wrappedBean, mbd);
 } catch (Throwable var6) {
  throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
 }

    //5.BeanPostProcessor后置处理
 if (mbd == null || !mbd.isSynthetic()) {
     //BeanPostProcessor接口的postProcessAfterInitialization回调
  wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }

 return wrappedBean;
}

AbstractAutowireCapableBeanFactory.invokeAwareMethods
invokeAwareMethod就是调用一系列Aware结尾的接口,比如
BeanNameAware、ApplicationContextAware、BeanFactoryAware。

private void invokeAwareMethods(String beanName, Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware)bean).setBeanName(beanName);
      }

       if (bean instanceof BeanClassLoaderAware) {
           ClassLoader bcl = this.getBeanClassLoader();
           if (bcl != null) {
               ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
           }
       }

       if (bean instanceof BeanFactoryAware) {
           ((BeanFactoryAware)bean).setBeanFactory(this);
       }
   }
 }

AbstractAutowireCapableBeanFactory.invokeInitMethods
invokeinitMethods就是调用InitializingBean接口的afterPropertiesSet,并且检查自定义init-method。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
 boolean isInitializingBean = bean instanceof InitializingBean;
 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
  if (System.getSecurityManager() != null) {
   try {
    AccessController.doPrivileged(() -> {
     ((InitializingBean)bean).afterPropertiesSet();
     return null;
    }, this.getAccessControlContext());
   } catch (PrivilegedActionException var6) {
    throw var6.getException();
   }
  } else {
   ((InitializingBean)bean).afterPropertiesSet();
  }
 }

 if (mbd != null && bean.getClass() != NullBean.class) {
  String initMethodName = mbd.getInitMethodName();
  if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
   this.invokeCustomInitMethod(beanName, bean, mbd);
  }
 }
}

从以上代码片段可以看出Spring IOC容器创建Bean的过程, 涉及的过程包括实例化,销毁,还包括BeanPostProcessor接口相关方法实现,以上代码片段我们分析了Spring容器初始化过程加载Bean的各种实现,下面我们看下Spring容器销毁阶段。

容器销毁

Spring容器销毁过程调用链

Spring在这里用了适配器模式,也就是说最终的销毁任务由DisposableBeanAdapter来完成,我们看下DisposeableBeanAdapter的结构。

从结构中可以看到bean属性类型为Object, 也就是要销毁的Bean,还有beanName属性。

public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        Iterator var1 = this.beanPostProcessors.iterator();

        while(var1.hasNext()) {
            DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }

 if (this.invokeDisposableBean) {
  try {
   if (System.getSecurityManager() != null) {
    AccessController.doPrivileged(() -> {
     ((DisposableBean)this.bean).destroy();
     return null;
    }, this.acc);
   } else {
    ((DisposableBean)this.bean).destroy();
   }
  } catch (Throwable var3) {
   
  }
 }

 if (this.destroyMethod != null) {
  this.invokeCustomDestroyMethod(this.destroyMethod);
 } else if (this.destroyMethodName != null) {
  Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
  if (methodToInvoke != null) {
   this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
  }
 }
}


总结

Spring Bean生命周期分为4个阶段和多个扩展点,扩展点又分为影响多个Bean和单个Bean。
4个阶段:实例化、属性赋值、初始化、销毁。
扩展点
影响多个Bean

  • BeanPostProcessor

  • InstantiationAwareBeanPostProcessor


影响单个Bean

  • BeanNameAware

  • BeanFactoryAware

  • BeanClassLoaderAware

  • ApplicationContextAware


Spring生命周期中两个关键的接口:InitializingBean, DisposableBean。






粉丝福利:Java从入门到入土学习路线图

👇👇👇

👆长按上方微信二维码 2 秒


感谢点赞支持下哈 

浏览 51
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报