前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring知识点(六)bean的生命周期

Spring知识点(六)bean的生命周期

作者头像
虞大大
发布2020-08-26 17:21:38
3330
发布2020-08-26 17:21:38
举报
文章被收录于专栏:码云大作战码云大作战

一、Bean的初始化

· 源码中bean的初始化方法的执行位置

(1)实现InitializingBean写的初始化方法

代码示例:

代码语言:javascript
复制
public class BeanMethodTest implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("bean初始化,afterPropertiesSet");
    }
}

执行位置:createBean—>doCreateBean—>initializeBean—>invokeInitMethods

代码语言:javascript
复制
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
      throws Throwable {
         //...         //执行bean实现了initializingBean接口中的方法         ((InitializingBean) bean).afterPropertiesSet();
          //...}

(2)在spring.xml中自定义初始化方法

代码示例:

代码语言:javascript
复制
<bean id="beanInitializingTest" class="com.ywl.leetcode.spring.life.BeanInitializingTest"
      init-method="customerInit"/>
代码语言:javascript
复制
@Component
public class BeanInitializingTest {
    public void customerInit(){
        System.out.println("初始化执行customerInit方法");
    }
}

执行位置:createBean—>doCreateBean—>initializeBean—>invokeInitMethods

代码语言:javascript
复制
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
      throws Throwable {
   //...
   if (mbd != null) {
      String initMethodName = mbd.getInitMethodName();
      if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
         invokeCustomInitMethod(beanName, bean, mbd);
      }
   }
}

(3)使用@PostConstruct注解

代码示例:

代码语言:javascript
复制
@Component
public class BeanInitializingTest {
    @PostConstruct
    public void initPostConstruct() {
        System.out.println("初始化执行initPostConstructt方法");
    }
}

执行位置:createBean—>doCreateBean—>initializeBean—>applyBeanPostProcessorsBeforeInitialization

代码语言:javascript
复制
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
      result = beanProcessor.postProcessBeforeInitialization(result, beanName);
      if (result == null) {
         return result;
      }
   }
   return result;
}

@PostConstruct所属于的后置处理器为CommonAnnotationBeanPostProcessors,在该后置处理器中对bean的@PostConstruct进行回调执行bean的初始化方法。

· bean的三种初始化执行顺序

根据源码中的执行顺序可以看到,先执行@PostContruct的回调方法、再执行实现了InitializingBean的初始化方法,最后执行spring.xml中指定的自定义初始化方法。

输出打印结果:

二、Bean的销毁

· 源码中bean的初始化方法的执行位置

(1)实现DisposableBean方法

代码语言:javascript
复制
public class BeanDestroyTest implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("销毁执行destroy方法");
    }
}

执行位置:destroySingleton—>destroyBean—>进入策略类,执行bean实现的destroy方法完成销毁。

代码语言:javascript
复制
protected void destroyBean(String beanName, DisposableBean bean) {
   //...
   if (bean != null) {
      try {
         bean.destroy();
      }
      catch (Throwable ex) {
         logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
      }
   }
   //...
}

(2)在spring.xml中自定义销毁方法

<bean id="beanDestroyTest" class="com.ywl.leetcode.spring.life.BeanDestroyTest" destroy-method="customerDestroy"/>

代码语言:javascript
复制
代码语言:javascript
复制
public class BeanDestroyTest {
    public void customerDestroy() throws Exception {
        System.out.println("销毁执行customerDestroy方法");
    }
}

执行位置:destroySingleton—>destroyBean—>进入策略类,org.springframework.beans.factory.support.DisposableBeanAdapter#destroy—>invokeCustomerDestroyMethod执行自定义方法完成bean的销毁。

代码语言:javascript
复制
private void invokeCustomDestroyMethod(final Method destroyMethod) {
         //...
         destroyMethod.invoke(bean, args);
代码语言:javascript
复制
         //...
代码语言:javascript
复制
}

· bean的二种销毁方法执行顺序

这二种销毁方法都是在bean.destroy中根据策略进行的,所以按照策略类的顺序,先执行实现了DisposableBean的销毁方法,后执行了自定义销毁方法。

输出打印结果:

二、Bean的Aware

aware相关执行顺序createBean—>doCreateBean—>initializeBean—>invokeAwareMethods,可以通过invokeAwareMethods调用具体的实现来处理或者拿到bean的相关name、beanFactory、classLoader。

代码语言:javascript
复制
private void invokeAwareMethods(final String beanName, final Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware) bean).setBeanName(beanName);
      }
      if (bean instanceof BeanClassLoaderAware) {
         ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
      }
      if (bean instanceof BeanFactoryAware) {
         ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
      }
   }
}

代码示例:

代码语言:javascript
复制
public class BeanAwareTest implements BeanFactoryAware                    , BeanNameAware, BeanClassLoaderAware {
    public BeanAwareTest() {
        System.out.println("构造函数初始化");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory方法");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName方法");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader方法");
    }
}

运行结果:

执行顺序就和源码中的一样,beanName—>beanClassLoader—>beanFactory。

三、Bean的后置处理器

代码示例:

代码语言:javascript
复制
public class BeanPostProcessorTest implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("beanMethodTest".equals(beanName)) {
            System.out.println("postProcessBeforeInitialization方法执行");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("beanMethodTest".equals(beanName)) {
            System.out.println("postProcessAfterInitialization方法执行");
        }
        return bean;
    }
}

输出结果:

· spring中真正的后置处理器方法调用位置

createBean—>doCreateBean—>initializeBean—>applyBeanPostProcessorsBeforeInitialization/applyBeanPostProcessorsAfterInitialization,并且applyBeanPostProcessorsBeforeInitialization先行发生于applyBeanPostProcessorsAfterInitialization。

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
   //...
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }
   //...
   if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
代码语言:javascript
复制
   //...
代码语言:javascript
复制
}

四、Bean的接口实现的调用顺序

综合以上所有bean的接口实现,观察调用顺序:

代码语言:javascript
复制
public class AllBeanLifeTest implements BeanFactoryAware, BeanNameAware, BeanClassLoaderAware
        , DisposableBean, InitializingBean {
    public AllBeanLifeTest() {
        System.out.println("构造函数初始化");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory方法");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName方法");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader方法");
    }

    public void customerDestroy() throws Exception {
        System.out.println("销毁执行customerDestroy方法");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁执行destroy方法");
    }

    @PostConstruct
    public void initPostConstruct() {
        System.out.println("初始化执行initPostConstruct方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化执行afterPropertiesSet方法");
    }

    public void customerInit() {
        System.out.println("初始化执行customerInit方法");
    }
}
代码语言:javascript
复制
public class BeanPostProcessorTest implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("allBeanLifeTest".equals(beanName)) {
            System.out.println("postProcessBeforeInitialization方法执行");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("allBeanLifeTest".equals(beanName)) {
            System.out.println("postProcessAfterInitialization方法执行");
        }
        return bean;
    }
}
代码语言:javascript
复制
<bean id="beanPostProcessorTest" class="com.ywl.leetcode.spring.life.BeanPostProcessorTest"/>
<bean id="allBeanLifeTest" class="com.ywl.leetcode.spring.life.AllBeanLifeTest"
      init-method="customerInit" destroy-method="customerDestroy"/>

运行结果:

从bean的接口实现和方法层面来说,大致的执行顺序为:

(1)bean早期对象的创建(即初始化完成)。

(2)bean实现了BeanNameAware则可以获取bean的name(即BeanNameAware实现方法的执行)。

(3)bean实现了BeanClassCloaderAware则可以获取bean的ClassLoader(即BeanClassCloaderAware实现方法的执行)。

(4)bean实现了BeanFactoryAware则可以获取bean的beanFactory(即BeanFactoryAware实现方法的执行)。

(5)后置处理器postProcessBeforeInitialization方法执行。

(6)@PostContrust注解的初始化方法执行。

(7)bean实现了InitializingBean的初始化实现方法的执行。

(8)spring.xml文件中配置的自定义初始化方法的执行。

(9)后置处理器postProcessAfterInitialization方法执行。

(10)bean实现了DisposableBean的销毁实现方法的执行。

(11)spring.xml文件中配置的自定义销毁方法的执行。

五、Bean的生命周期总结

spring bean的生命周期即从spring容器开始到spring容器关闭中bean的过程,结合上面的流程以及前几篇的内容,这里用画图的形式来总结下bean的生命周期。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码云大作战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档