spring中Bean的生命周期

  Spring容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。

  而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

 

Bean生命周期

  Spring Bean的生命周期只有4个阶段:

  1. 实例化 Instantiation:根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
  2. 属性赋值 Populate:利用依赖注入完成 Bean 中所有属性值的配置注入。
  3. 初始化 Initialization:根据Bean的不同定义,完成不同的初始化。比如Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
  4. 销毁 Destruction

"Spring Bean的生命周期可以分为四个主要阶段:实例化、属性赋值、初始化、销毁。

首先,Spring通过反射实例化Bean。然后进行属性填充,完成依赖注入。接着,Spring会回调一系列Aware接口,让Bean获取容器相关信息。

在初始化阶段,Spring先调用BeanPostProcessor的前置处理方法,然后依次执行@PostConstruct注解方法、InitializingBean接口、以及自定义init-method。初始化完成后,会调用BeanPostProcessor的后置处理方法——这里是AOP创建代理的关键点。

最后,当容器关闭时,会依次执行@PreDestroy、DisposableBean接口和自定义destroy-method来完成销毁。

其中最重要的是BeanPostProcessor,它是Spring扩展性的基石,AOP、注解扫描等核心功能都依赖它来实现。"

代码层面梳理生命周期

@Component
public class LifecycleDemoBean implements BeanNameAware, BeanFactoryAware, 
        ApplicationContextAware, InitializingBean, DisposableBean {
    
    private String name;
    
    public LifecycleDemoBean() {
        System.out.println("1. 实例化: 构造函数执行");
    }
    
    public void setName(String name) {
        System.out.println("2. 属性赋值: setName方法执行");
        this.name = name;
    }
    
    @Override
    public void setBeanName(String name) {
        System.out.println("3. BeanNameAware: setBeanName执行");
    }
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        System.out.println("4. BeanFactoryAware: setBeanFactory执行");
    }
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println("5. ApplicationContextAware: setApplicationContext执行");
    }
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("6. @PostConstruct: 初始化前置方法执行");
    }
    
    @Override
    public void afterPropertiesSet() {
        System.out.println("7. InitializingBean: afterPropertiesSet执行");
    }
    
    public void initMethod() {
        System.out.println("8. init-method: 自定义初始化方法执行");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("11. @PreDestroy: 销毁前置方法执行");
    }
    
    @Override
    public void destroy() {
        System.out.println("12. DisposableBean: destroy执行");
    }
    
    public void destroyMethod() {
        System.out.println("13. destroy-method: 自定义销毁方法执行");
    }
}
View Code

第一阶段:实例化前准备

1. 扫描与解析

Spring启动时,会扫描指定包下的类,将带有@Component等注解的类解析为BeanDefinition,注册到BeanFactory

2. 合并BeanDefinition

如果Bean有父类,Spring会合并父子Bean的定义信息。

第二阶段:实例化阶段

3. 实例化

Spring通过反射创建Bean的实例。对应输出:"1. 实例化: 构造函数执行",此时Bean还是一个"半成品",属性都还是默认值。

// AbstractAutowireCapableBeanFactory.doCreateBean
instanceWrapper = createBeanInstance(beanName, mbd, args);

第三阶段:属性赋值阶段

4. 属性填充

Spring将依赖的其他Bean、配置的值注入到当前Bean中。对应输出:"2. 属性赋值: setName方法执行",这是依赖注入发生的地方,@Autowired@Value@Resource在这里处理。

populateBean(beanName, mbd, instanceWrapper);

第四阶段:Aware接口回调

Aware接口是Spring提供的感知型接口,让普通Bean能够获取容器级别的资源和服务。

核心作用有两个:一是让Bean获得对容器的访问能力,比如获取ApplicationContext来发布事件、获取Environment来读取配置;二是解决一些特殊场景的需求,比如通过BeanFactoryAware获取Bean的代理对象来解决事务自调用失效的问题。

Aware的回调发生在Bean生命周期的属性赋值之后、初始化方法之前。Spring通过两个阶段处理Aware:BeanFactoryAware等直接在容器内部调用,而ApplicationContextAware等通过BeanPostProcessor处理。

5. BeanNameAware

如果Bean实现了BeanNameAware,Spring会将Bean的id传入。对应输出:"3. BeanNameAware: setBeanName执行"

6. BeanFactoryAware

如果实现了BeanFactoryAware,Spring会将当前的BeanFactory传入。对应输出:"4. BeanFactoryAware: setBeanFactory执行"

7. ApplicationContextAware

如果实现了ApplicationContextAware,Spring会将当前的ApplicationContext传入。对应输出:"5. ApplicationContextAware: setApplicationContext执行"

第五阶段:BeanPostProcessor前置处理

8. BeanPostProcessor.postProcessBeforeInitialization

在所有初始化方法执行之前,Spring会调用所有BeanPostProcessorpostProcessBeforeInitialization方法。

这是非常重要的扩展点,很多框架在这里做手脚:

  • ApplicationContextAwareProcessor:处理各种Aware接口

  • InitDestroyAnnotationBeanPostProcessor:扫描@PostConstruct等注解

对应输出:这一步没有直接输出,但它会触发第9步

第六阶段:初始化阶段

9. @PostConstruct注解方法

如果Bean中有方法标注了@PostConstruct,在这里执行。对应输出:"6. @PostConstruct: 初始化前置方法执行"

10. InitializingBean.afterPropertiesSet()

如果Bean实现了InitializingBean接口,在这里执行。对应输出:"7. InitializingBean: afterPropertiesSet执行"

11. init-method

如果XML配置或@Bean(initMethod = "xxx")指定了初始化方法,在这里执行。对应输出:"8. init-method: 自定义初始化方法执行"

// AbstractAutowireCapableBeanFactory.invokeInitMethods
if (bean instanceof InitializingBean) {
    ((InitializingBean) bean).afterPropertiesSet();
}
if (mbd.getInitMethodName() != null) {
    invokeCustomInitMethod(beanName, bean, mbd);
}

第七阶段:BeanPostProcessor后置处理

12. BeanPostProcessor.postProcessAfterInitialization

在初始化方法执行之后,Spring调用所有BeanPostProcessorpostProcessAfterInitialization方法。

这里是AOP代理创建的地方!

  • AbstractAutoProxyCreator在这里检查是否需要为当前Bean创建代理

  • 如果需要,这里返回的是代理对象,而不是原始Bean

对应输出:没有直接输出,但这一步完成后,Bean就可以使用了。

// AbstractAutowireCapableBeanFactory.initializeBean
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;

第八阶段:使用阶段

13. Bean就绪

Bean已经准备就绪,驻留在容器中,等待被应用程序使用。

第九阶段:销毁阶段

当容器关闭时,销毁流程开始:

14. @PreDestroy注解方法

如果Bean中有方法标注了@PreDestroy,在这里执行。对应输出:"11. @PreDestroy: 销毁前置方法执行"

15. DisposableBean.destroy()

如果Bean实现了DisposableBean接口,在这里执行。对应输出:"12. DisposableBean: destroy执行"

16. destroy-method

如果指定了自定义销毁方法,在这里执行。对应输出:"13. destroy-method: 自定义销毁方法执行"

 
 
posted @ 2017-12-26 00:27  鄙人取个名字好难  阅读(817)  评论(0)    收藏  举报