Spring Bean生命周期详解

  本文结合Spring源码5.1.7.RELEASE,详细分析Spring Bean生命周期,包括主要流程以及Spring一系列的扩展方法,最后通过测试实例演示主要步骤。

  Spring提供的Bean扩展方法大致分为三类,一类是BeanPostProcessor接口,一类是BeanFactoryProcessor接口,还有一类是Aware接口。

  Spring Bean的生命周期概括下来,主要分4个大阶段:实例化-->属性赋值-->初始化-->销毁。主要流程图如下:

  以下部分,按步骤分别解析各个阶段。

一、BeanDefination解析及合并

  首先说明一个概念,BeanDefination是什么?BeanDefination就是Bean的元信息,用来描述Bean的各种信息,包括Bean作用域、是否是Primary、字段值、初始化方法等,Bean的元信息的抽象。在Spring创建Bean之前,会有Bean的元信息解析及合并。

  元信息的解析发生在AbstractApplicationContext#refresh-->obtainFreshBeanFactory()-->AbstractRefreshableApplicationContext#refreshBeanFactory()-->loadBeanDefinitions()方法。loadBeanDefinitions是一个抽象方法,Spring有不同类型的实现,包括xml解析、注解解析等。

  

 

 

 

 

 

 

 

 

 

 

  

  

  元信息之所以需要做合并,就是因为Java的继承,子类的Bean在进行装配之前,必须把其父类的元信息合并到当前子类当中。元信息的合并发生在AbstractBeanFactory#doGetBean方法中。

  getMergedLocalBeanDefinition()方法跟踪到最后一步,分析getMergedBeanDefinition方法源码分析如下:

 二、实例化

2.1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

  元信息准备好之后,进入Bean实例化阶段,来到流程图中的第一个扩展接口InstantiationAwareBeanPostProcessor。

  首先看看AbstractAutowireCapableBeanFactory#createBean的代码:

  跟踪调用点方法resolveBeforeInstantiation,代码如下:

   结合两个方法的代码逻辑可知,在开始实例化之前,如果resolveBeforeInstantiation返回有Bean的实例,后续doCeateBean方法里全部逻辑,即属性赋值、初始化等,都不会再执行。

InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法默认实现是返回null,所以可以自行实现该接口,在创建Bean的时候返回特定的Bean实例,用作代理,替换原来的Bean,这里也是Spring AOP编程的体现。
2.2 实例化createBeanInstance

  Bean的实例化、属性赋值和初始化三个阶段的代码都在AbstractAutowireCapableBeanFactory#doCreateBean方法中,代码如下:

    createBeanInstance方法简单来说,就是通过构造器方法实例化对象的过程,代码解析如下:

2.3 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

  postProcessAfterInstantiation方法的调用点在属性赋值方法populateBean当中,代码解析如下:

   InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation接口的作用是判断是否需要为Bean进行后续的属性赋值。用户可实现该接口,为指明的Bean跳过属性赋值阶段,但后续的初始化依然会执行。

、属性赋值

3.1 InstantiationAwareBeanPostProcessor#postProcessProperties

  通过populateBean的代码解析可知,postProcessProperties和postProcessPropertyValues都是为了获取PropertyValues。PropertyValues封装的是以K-V形式存储的Bean的属性和值。实现postProcessProperties方法,就可对特定的Bean对象的初始属性值进行自定义设置和修改。

 3.2 属性填充applyPropertyValues

  属性填充的过程很简单,就是直接把PropertyValues填充到BeanWrapper中。BeanWrapper是对Bean的包装,将对Bean属性访问和类型转换相关的操作封装到BeanWrapper。

四、初始化

  初始化的代码解析如下:

4.1 Aware接口回调--第一部分

  Aware是Spring开放出来的,用于对Bean起标识作用的超级接口。Spring一系列Aware接口的执行顺序如流程图所示,分两部分。

  第一部分的BeanNameAware、BeanClassLoaderAware和BeanFactoryAware在initializeBean方法中的invokeAwareMethod方法中调用。代码解析如下:

   声明的Bean可以实现Spring全部的Aware接口,重写相应的set方法,即可对当前的Bean进行相应的增强和描述。

4.2 BeanPostProcessor#postProcessBeforeInitialization

  Aware接口的第二部分部分调用在applyBeanPostProcessorsBeforeInitialization方法中。applyBeanPostProcessorsBeforeInitialization实际调用BeanPostProcessor#postProcessBeforeInitialization。在BeanPostProcessor的实现类ApplicationContextAwareProcessor重写了postProcessBeforeInitialization方法。

  ApplicationContextAwareProcessor#postProcessBeforeInitialization中,有第二部分Aware接口:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware的调用链。

  值得另外说明的是, BeanPostProcessor还有一个实现类InitDestroyAnnotationBeanPostProcessor,同样重写了postProcessBeforeInitialization方法。这里在调用BeanPostProcessor#postProcessBeforeInitialization方法时,InitDestroyAnnotationBeanPostProcessor也会被触发。InitDestroyAnnotationBeanPostProcessor类用于调用Bean中声明了@PostConstruct和@PreDestroy注解的初始化方法和销毁方法。

4.3 InitializingBean#afterPropertiesSet

  afterPropertiesSet方法是Bean初始化方式的一种,Bean自己可以实现InitializingBean接口,在invokeInitMethods方法达到调用点时触发afterPropertiesSet,进行Bean初始化操作。代码解析如下:

4.4 自定义初始化方法

  声明Bean的时候,还可以指定自定义初始化方法,也就是@Bean注解中initMethod属性。invokeCustomInitMethod会通过反射调用initMethod指明的,Bean中自定义的方法。

  如果Bean同时声明了上面三种初始化方法,那么这里的执行顺序就是:@PostConstruct--->InitializingBean#afterPropertiesSet--->initMethod。

4.5 BeanPostProcessor#postProcessAfterInitialization

  在初始化方法全部执行结束之后,紧接着就会开始调用postProcessAfterInitialization方法。代码解析如下:

  从代码中可以看到,如果postProcessAfterInitialization返回的对象不为空,会用返回的对象替换前面初始化好的对象。

  整个流程执行到这里,代表Bean已经创建好了。后续根据作用域的不同,情况亦不同,单例的Bean由Spring负责销毁,其他由用户自己控制生命周期的终结。

五、销毁

   Bean的销毁阶段的代码逻辑在DisposableBeanAdapter#destroy方法中,代码解析如下:

  这里的第一步需要注意,DestructionAwareBeanPostProcessor是一个接口,也就是说,用户可以自定义接口实现,重写postProcessBeforeDestruction方法实现自己的逻辑。然后Spring本身有一个类CommonAnnotationBeanPostProcessor,实现了DestructionAwareBeanPostProcessor接口,用于处理@Predestory和@PostConstruct注解逻辑,这里也会执行。

  从上面代码解析可以看到,Sping Bean的销毁阶段跟初始化阶段类似,也存在三种销毁方法,其执行步骤是:@Predestory--->DisposableBean#destory--->自定义destory方法。

 六、代码演示

  根据上述二到五部分的源码解析,编写演示代码。

6.1 自定义InstantiationAwareBeanPostProcessor

复制代码
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("1. 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("3. 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("4. 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法");
        }
        return null;
    }
}
复制代码

6.2 自定义BeanPostProcessor

复制代码
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("10. 调用 BeanPostProcessor.postProcessBeforeInitialization() 方法");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("user".equals(beanName)) {
            System.out.println("14. 调用 BeanPostProcessor.postProcessAfterInitialization() 方法");
        }
        return bean;
    }
}
复制代码

6.3 Bean定义

复制代码
@Data
public class User implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware, BeanClassLoaderAware,
        BeanFactoryAware, EnvironmentAware {

    private int id;

    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
        System.out.println("2. 调用构造函数");
    }

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

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

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

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("8. 调用 EnvironmentAware.setEnvironment() 方法");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("9. 调用 ApplicationContextAware.setApplicationContext() 方法");
    }

    @PostConstruct
    public void postInit() {
        System.out.println("11. 调用 PostConstruct 初始化 方法");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("12. 调用 InitializingBean.afterPropertiesSet() 方法");
    }

    public void myInit() {
        System.out.println("13. 调用 init-method 方法");
    }

    @PreDestroy
    public void myDestroy() {
        System.out.println("15. 调用 PreDestroy 方法");
    }


    @Override
    public void destroy() {
        System.out.println("16. 调用 DisposableBean.destroy() 方法");
    }

    public void myDestroyMethod() {
        System.out.println("17. 调用 destroy-method 方法");
    }
}
复制代码

  测试代码运行效果如下:

  测试效果符合流程图所示。

  到此,Spring Bean生命周期全阶段解析完成。

posted @   阳光、大地和诗歌  阅读(1238)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示