一、概述
1. Bean的生命周期
Bean的生命周期包括Bean的创建、存活、销毁的过程,创建就是实例化的过程,存活包括属性赋值和初始化,所以又说Bean的生命周期为:实例化、属性赋值、初始化和销毁,而这个过程单例和多例有所不同:
【1】单例Bean
- 实例化:容器启动的时候实例化对象
- 存活:只要容器还在,Bean对象就一直存活(和容器共存亡)
- 销毁:容器关闭的时候就销毁
【2】多例Bean
- 实例化:获取对象的时候实例化对象
- 存活:对象只要在使用过程中就一直存活
- 销毁:当对象长时间不用且没有其他对象引用时,由Java垃圾回收器回收
2. 处理生命周期
在我们开发过程中,我们一般都会对初始化前后进行一些处理,处理的方式比较多,可以使用注解,也可以用实现类,总结为以下四点:
【1】指定方法
可以指定初始化和销毁方法:
- 通过@Bean注解指定
initMethod和destroyMethod
【2】实现接口
实现接口:
-
InitializingBean接口:定义初始化逻辑
-
DisposableBean接口:定义销毁逻辑
【3】JSR 250注解规范
JSR是Java Specification Requests的缩写,意思是Java 规范提案,JSR 250 规范包含用于将资源注入到端点实现类的注释和用于管理应用程序生命周期的注释。
使用JSR250:
-
@PostConstruct注解:在Bean创建完成并赋值完成执行初始化方法
-
@PreDestroy注解:在容器销毁容器之前提醒我们进行清理工作
【4】后置处理器
BeanPostProcessor接口:Bean的后置处理器,在Bean初始化前后进行一些处理工作
-
postProcessBeforeInitialization:在初始化之前工作
-
postProcessAfterInitialization:在初始化之后工作
二、实例分析
【1】指定方法
可以通过@Bean注解指定初始化和销毁方法:initMethod和destroyMethod,以Dog对象为例子:
// 启动类
public class MainTest {
@Test
public void TestMain() {
// 创建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// applicationContext.getBean("dog");
applicationContext.close();
}
}
// 待注入的Bean
public class Dog {
public Dog(){
System.out.println("dog create");
}
public void init(){
System.out.println("dog init");
}
public void destroy(){
System.out.println("dog destroy");
}
}
// 配置类
@Configuration
public class AppConfig {
// @Scope("prototype")
// 通过@Bean注解指定初始化和销毁方法
@Bean(initMethod = "init",destroyMethod = "destroy")
public Dog dog(){
return new Dog();
}
}
这是单实例场景下的案例,单实例是在容器启动的时候实例化对象,容器关闭的时候进行销毁,可以看到,通过@Bean(initMethod = "init",destroyMethod = "destroy"),可以指定初始化和销毁方法。
如果是多实例,将配置类中的@Scope("prototype")放开,多实例是在获取对象的时候实例化对象,这时,直接运行启动类啥都不会打印,因为没有获取对象,也就没有初始化和销毁,因此需要将启动类中的applicationContext.getBean("dog");放开,获取对象,此时运行启动类,进行了创建Bean和初始化Bean,而销毁则当对象长时间不用且没有其他对象引用时,由Java垃圾回收器回收。
【2】实现接口
将Bean对象实现InitializingBean, DisposableBean接口,重写destroy和afterPropertiesSet方法进行销毁和初始化,注意要@Component注解将Bean注入容器中,并在配置类中使用@ComponentScan注解进行扫描,以cat对象为例子:
// 启动类
@Test
public void TestMain() {
// 创建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
applicationContext.close();
}
// 待注入的Bean
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat(){
System.out.println("cat create");
}
// 销毁Bean
public void destroy() throws Exception {
System.out.println("cat destroy");
}
// 初始化Bean
public void afterPropertiesSet() throws Exception {
System.out.println("cat afterPropertiesSet");
}
}
// 配置类
@ComponentScan("bean")
@Configuration
public class AppConfig {
}
实现InitializingBean, DisposableBean接口,重写destroy和afterPropertiesSet方法进行销毁和初始化,可以看到进行初始化和销毁:
【3】使用JSR250注解规范
使用JSR250注解规范,通过@PostConstruct注解和@PreDestroy注解进行对象的创建赋值调用和销毁对象,以pig对象为例:
// 启动类
@Test
public void TestMain() {
// 创建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
applicationContext.close();
}
// 待注入的Bean
@Component
public class Pig {
public Pig(){
System.out.println("pig create");
}
// @PostConstruct:对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("pig postConstruct");
}
// @PreDestroy:容器移除对象之前
@PreDestroy
public void destroy(){
System.out.println("pig destroy");
}
}
// 配置类
@ComponentScan("bean")
@Configuration
public class AppConfig {
}
使用@PostConstruct注解作用来初始化方法上面,@PreDestroy注解作用在销毁方法上面,运行启动类,可以看到进行初始化和销毁:
【4】后置处理器
后置处理器是在Bean初始化前后进行一些处理工作,实现BeanPostProcessor类,重写方法,postProcessBeforeInitialization在初始化之前工作,postProcessAfterInitialization在初始化之后工作,在pig对象实例中添加:
@Component // 将后置处理器加入到容器中
public class MyBeanPostProcessor implements BeanPostProcessor {
// postProcessBeforeInitialization:在初始化之前工作
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization" + beanName + "===" + bean);
return bean;
}
// postProcessAfterInitialization:在初始化之后工作
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization" + beanName + "===" + bean);
return bean;
}
}
在pig对象初始化前后执行相应的代码,运行结果如下:
三、源码追踪
在spring源码中,BeanPostProcessor后置处理器是一个非常重要的类,我们来看看spring底层是如何实现Bean初始化的
【1】刷新容器
IOC容器构造器调用refresh方法刷新容器
public AnnotationConfigApplicationContext(String... basePackages) {
this();
this.scan(basePackages);
// 刷新容器
this.refresh();
}
【2】获取实例
调用refresh中的finishBeanFactoryInitialization方法初始化所有单实例对象
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
// 初始化所有单实例对象
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}
this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}
}
}
- 到
preInstantiateSingletons类中调用getBean方法 - 调用
doGetBean - 调用
getSingleton获取单实例 - 如果获取不到则调用
createBean创建实例
this.getBean(beanName);
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
if (mbd.isSingleton()) {
// 获取单实例
sharedInstance = this.getSingleton(beanName, () -> {
try {
// 如果获取不到则调用createBean创建实例
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建实例
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
【3】创建实例
如何创建的呢,我们继续看源码,追踪到doCreateBean类中的initializeBean方法,在这个方法之前有个populateBean方法
- populateBean:为Bean属性赋值
- initializeBean:相当于后置处理器的调用
try {
// 为Bean属性赋值
this.populateBean(beanName, mbd, instanceWrapper);
// 相当于后置处理器的调用
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
调用initializeBean方法中的invokeInitMethods方法执行初始化方法,在上面提到的实现接口、使用注解、自定义初始化都是在这个方法中执行的,注意看这个方法的前后:
- applyBeanPostProcessorsBeforeInitialization
- applyBeanPostProcessorsAfterInitialization
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
// 执行初始化方法
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
点开这两个方法查看源码:
applyBeanPostProcessorsBeforeInitialization
- 遍历得到所有的BeanPostProcessors
- 挨个执行BeforeInitialization
- 为空则直接返回,不会执行后面的BeanPostProcessors.postProcessBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
// 遍历得到所有的BeanPostProcessors,挨个执行BeforeInitialization,为空则直接返回,不会执行后面的BeanPostProcessors.postProcessBeforeInitialization
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
四、总结
BeanPostProcessors原理:
- 通过
getBean获取实例 - 获取不到则通过
createBean创建实例 - 在
doCreateBean类中通过populateBean为实例属性赋值 - 调用
initializeBean方法中的invokeInitMethods方法执行初始化方法 - 在实例初始化前后分别执行
applyBeanPostProcessorsBeforeInitialization、applyBeanPostProcessorsAfterInitialization,也就是后置处理器在实例初始化前后所要做的工作