youyichannel

志于道,据于德,依于仁,游于艺!

0%

梳理 Spring Bean 生命周期

Spring 容器可以管理 Singleton 作用域的 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建、何时初始化完成、何时被销毁。对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器不再追踪其生命周期。

Spring Bean 的生命周期流程

1)如果 BeanFactoryPostProcessorBean 关联, 则调用postProcessBeanFactory方法,即首先尝试从Bean工厂中获取Bean

2)如果 InstantiationAwareBeanPostProcessorBean 关联,则调用postProcessBeforeInstantiation() 方法;

3)根据配置情况调用 Bean 构造方法 实例化 Bean

4)利用依赖注入完成 Bean 中所有 属性值的配置注入

5)如果 InstantiationAwareBeanPostProcessorBean 关联,则调用postProcessAfterInstantiation()方法和 postProcessProperties()

6)调用 xxxAware 接口

  • 第一类 Aware 接口

    • 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值;

    • 如果 Bean 实现了 BeanClassLoaderAware 接口,则 Spring 调用 setBeanClassLoader() 方法传入 classLoader 的引用;

    • 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用;

  • 第二类Aware接口

    • 如果 Bean 实现了 EnvironmentAware 接口,则 Spring 调用 setEnvironment() 方法传入当前 Environment 实例的引用;

    • 如果 Bean 实现了 EmbeddedValueResolverAware 接口,则 Spring 调用 setEmbeddedValueResolver() 方法传入当前 StringValueResolver 实例的引用;

    • 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用;

    • ...

7)如果 BeanPostProcessorBean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzationBean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。

8)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet 方法;(或者有执行 @PostConstruct 注解的方法)

9)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。

10)如果 BeanPostProcessorBean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization。此时,Bean 已经可以被应用系统使用了;

11)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean;

12)使用 Bean;

13)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory 方法将 Spring 中的 Bean 销毁;(或者有执行 @PreDestroy 注解的方法)

14)如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。

Bean 的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类

  1. Bean 自身的方法:包括 Bean 本身调用的方法和通过配置文件中 <bean>init-methoddestroy-method 指定的方法
  2. Bean 级生命周期接口方法:包括 BeanNameAwareBeanFactoryAwareApplicationContextAware;也包括 InitializingBeanDiposableBean 这些接口的方法(可以被 @PostConstruct@PreDestroy 注解替代)
  3. 容器级生命周期接口方法:包括 InstantiationAwareBeanPostProcessorBeanPostProcessor 这两个接口实现,一般称它们的实现类为「后处理器」
  4. 工厂后处理器接口方法:包括 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的,在应用上下文装配配置文件之后立即调用

Spring Bean 生命周期案例探索

定义Bean,此处为 User,并让其实现 BeanFactoryAwareBeanNameAwareApplicationContextAwareInitializingBeanDisposableBean 接口

@Slf4j
@ToString
public class User implements BeanFactoryAware, BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {

private String name;

private int age;

private BeanFactory beanFactory;

private ApplicationContext applicationContext;

private String beanName;

public User() {
log.info("execute User#new User()");
}

public void setName(String name) {
log.info("execute User#setName({})", name);
this.name = name;
}

public void setAge(int age) {
log.info("execute User#setAge({})", age);
this.age = age;
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
log.info("execute BeanFactoryAware#setBeanFactory()");
this.beanFactory = beanFactory;
}

@Override
public void setBeanName(String beanName) {
log.info("execute BeanNameAware#setBeanName({})", beanName);
this.beanName = beanName;
}

@Override
public void destroy() throws Exception {
log.info("execute DisposableBean#destroy()");
}

@Override
public void afterPropertiesSet() throws Exception {
log.info("execute InitializingBean#afterPropertiesSet()");
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("execute ApplicationContextAware#setApplicationContext()");
this.applicationContext = applicationContext;
}

public void doInit() {
log.info("execute User#doInit()");
}

public void doDestroy() {
log.info("execute User#doDestroy()");
}
}

定义一些 Processor:

@Slf4j
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
log.info("execute BeanFactoryPostProcessor#postProcessBeanFactory()");
}
}

@Slf4j
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
log.info("execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation() for {}", beanName);
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
log.info("execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation() for {}", beanName);
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
log.info("execute InstantiationAwareBeanPostProcessor#postProcessProperties() for {}", beanName);
return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
}
}

@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
log.info("execute BeanPostProcessor#postProcessBeforeInitialization() for {}", beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
log.info("execute BeanPostProcessor#postProcessAfterInitialization() for {}", beanName);
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}

初始化 User Bean:

@Configuration
public class BeanConfig {

@Bean(name = "user", initMethod = "doInit", destroyMethod = "doDestroy")
public User create() {
User user = new User();
user.setName("youyichannel");
user.setAge(20);
return user;
}

}

主类:

@Slf4j
public class App {

public static void main(String[] args) {
log.info("Init application context");

// create and configure beans
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.youyi.springframework");

User user = (User) context.getBean("user");

log.info(user.toString());

log.info("Shutdown application context");
context.registerShutdownHook();
}
}

输出日志(删减之后):

13:04:12.407 [main] INFO com.youyi.springframework.App - Init application context
13:04:12.622 [main] INFO com.youyi.springframework.processor.MyBeanFactoryPostProcessor - execute BeanFactoryPostProcessor#postProcessBeanFactory()
13:04:12.645 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'user'
13:04:12.645 [main] INFO com.youyi.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation() for user
13:04:12.650 [main] INFO com.youyi.springframework.entity.User - execute User#new User()
13:04:12.650 [main] INFO com.youyi.springframework.entity.User - execute User#setName(youyichannel)
13:04:12.650 [main] INFO com.youyi.springframework.entity.User - execute User#setAge(20)
13:04:12.651 [main] INFO com.youyi.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation() for user
13:04:12.651 [main] INFO com.youyi.springframework.processor.MyInstantiationAwareBeanPostProcessor - execute InstantiationAwareBeanPostProcessor#postProcessProperties() for user
13:04:12.652 [main] INFO com.youyi.springframework.entity.User - execute BeanNameAware#setBeanName(user)
13:04:12.652 [main] INFO com.youyi.springframework.entity.User - execute BeanFactoryAware#setBeanFactory()
13:04:12.652 [main] INFO com.youyi.springframework.entity.User - execute ApplicationContextAware#setApplicationContext()
13:04:12.660 [main] INFO com.youyi.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessBeforeInitialization() for user
13:04:12.660 [main] INFO com.youyi.springframework.entity.User - execute InitializingBean#afterPropertiesSet()
13:04:12.661 [main] INFO com.youyi.springframework.entity.User - execute User#doInit()
13:04:12.661 [main] INFO com.youyi.springframework.processor.MyBeanPostProcessor - execute BeanPostProcessor#postProcessAfterInitialization() for user
13:04:12.674 [main] INFO com.youyi.springframework.App - User(name=youyichannel, age=20)
13:04:12.674 [main] INFO com.youyi.springframework.App - Shutdown application context
13:04:12.675 [SpringContextShutdownHook] INFO com.youyi.springframework.entity.User - execute DisposableBean#destroy()
13:04:12.675 [SpringContextShutdownHook] INFO com.youyi.springframework.entity.User - execute User#doDestroy()