Spring 容器可以管理 Singleton
作用域的
Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean
何时被创建、何时初始化完成、何时被销毁。对于
prototype
作用域的 Bean,Spring
只负责创建,当容器创建了 Bean 的实例后,Bean
的实例就交给客户端代码管理,Spring 容器不再追踪其生命周期。
Spring Bean 的生命周期流程
1)如果 BeanFactoryPostProcessor
和 Bean
关联,
则调用postProcessBeanFactory
方法,即首先尝试从Bean工厂中获取Bean;
2)如果 InstantiationAwareBeanPostProcessor
和
Bean
关联,则调用postProcessBeforeInstantiation()
方法;
3)根据配置情况调用 Bean
构造方法 实例化
Bean;
4)利用依赖注入完成 Bean
中所有
属性值的配置注入;
5)如果 InstantiationAwareBeanPostProcessor
和
Bean
关联,则调用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)如果 BeanPostProcessor
和 Bean
关联,则
Spring 将调用该接口的预初始化方法
postProcessBeforeInitialzation
对 Bean
进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
8)如果 Bean
实现了 InitializingBean
接口,则 Spring 将调用 afterPropertiesSet
方法;(或者有执行
@PostConstruct
注解的方法)
9)如果在配置文件中通过 init-method
属性指定了初始化方法,则调用该初始化方法。
10)如果 BeanPostProcessor
和 Bean
关联,则
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
的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
- Bean 自身的方法:包括 Bean
本身调用的方法和通过配置文件中
<bean>
的
init-method
和 destroy-method
指定的方法
- Bean 级生命周期接口方法:包括
BeanNameAware
、BeanFactoryAware
、ApplicationContextAware
;也包括
InitializingBean
和 DiposableBean
这些接口的方法(可以被 @PostConstruct
和
@PreDestroy
注解替代)
- 容器级生命周期接口方法:包括
InstantiationAwareBeanPostProcessor
和
BeanPostProcessor
这两个接口实现,一般称它们的实现类为「后处理器」
- 工厂后处理器接口方法:包括
AspectJWeavingEnabler
,
ConfigurationClassPostProcessor
,
CustomAutowireConfigurer
等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的,在应用上下文装配配置文件之后立即调用
Spring Bean 生命周期案例探索
定义Bean,此处为 User
,并让其实现
BeanFactoryAware
、BeanNameAware
、ApplicationContextAware
、InitializingBean
、DisposableBean
接口
@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");
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()
|