在 Spring
框架中,容器可以对 Singleton
作用域下的 bean
进行生命周期管理,对 bean
的创建、初始化和销毁进行控制。本文讲述 bean
的生命周期全过程,详细描述了生命周期过程中 spring
开放的自定义切入接口。
生命周期流程图:
一、定义Bean
在程序启动最初,Spring
可通过 xml
文件、注解或 javaApi
的方式创建 BeanDefinition
。
BeanFactoryPostProcessor
是 bean
工厂的后置处理器,在 BeanDefinition
全部扫描创建完成后执行,可以在容器的 bean
创建之前修改 bean
工厂和 BeanDefinition
。
二、实例化与属性注入
当客户向容器请求一个尚未初始化的 bean
时,或初始化 bean
时需要注入另一个尚末初始化的依赖时,容器就会调用 doCreateBean
方法通过反射的方式创建出一个 bean
对象。
bean
实例创建之后,doCreateBean
方法通过调用 populateBean
方法对这个 bean
进行属性填充。
三、初始化Bean
Bean
初始化过程对应 initializeBean
方法,将被 doCreateBean
方法调用。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 执行 BeanNameAware、BeanClassLoaderAware和BeanFactoryAware
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 执行 BeanPostProcessor 接口的 postProcessBeforeInitialization 方法。
// 除了上述的三个 Aware 接口,其余的 Aware 接口通过 BeanPostProcessor 接口实现,具体实现类为
// ApplicationContextAwareProcessor。
// 初始化 bean 的扩展插入注解 @PostConstruct 通过 CommonAnnotationBeanPostProcessor
// 接口实现。
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 执行 InitializingBean 接口和 init-method 参数两种扩展方式插入的方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 执行 BeanPostProcessor 接口的 postProcessAfterInitialization 方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
如上源码所示:
-
初始化
bean
最初,容器会检测bean
是否实现了内置的xxxAware
接口,如果实现了则执行相应的接口方法。通过
xxxAware
接口,可以让bean
拿到Spring
容器的一些资源。常见
Aware
接口:- ApplicationContextAware:获取容器本身
ApplicationContext
对象; - ApplicationEventPublisherAware:获取事件发布器的接口;
- BeanClassLoaderAware:获取加载当前
bean
的类加载器; - BeanFactoryAware: 获取当前
bean
的BeanFactory
实例,可以用来手动注册bean
; - BeanNameAware:在获取
bean
在容器中的的名称; - ResourceLoaderAware:获取
ResourceLoader
实例,获取资源加载器读取资源文件。
- ApplicationContextAware:获取容器本身
-
在执行完
BeanNameAware
、BeanClassLoaderAware
和BeanFactoryAware
之后,执行初始化扩展之前,spring
执行BeanPostProcessor
后置处理器的postProcessBeforeInitialization
方法。值得注意的是,
Aware
、初始化扩展方法与BeanPostProcessor
职责并非明确划分的,他们也通过BeanPostProcessor
实现功能。除了上述的三种
Aware
接口,其余的Aware
接口都是通过BeanPostProcessor
的实现类ApplicationContextAwareProcessor
在此处完成的调用。初始化扩展注解
@PostConstruct
通过CommonAnnotationBeanPostProcessor
实现。通过控制
BeanPostProcessor
列表的顺序,从而使初始化的执行步骤有序。
-
在初始化
bean
时spring
提供了三种扩展方式,三种扩展方式可同时使用,但不能同时指向同一个方法,多个扩展指向同一个方法这个方法也只会执行一次。扩展方法执行顺序为:
@PostConstruct
注解 ->InitializingBean
接口 ->init-method
参数指定。 -
在执行自定义初始化方法之后,
spring
最后执行BeanPostProcessor
后置处理器的postProcessAfterInitialization
方法,完成bean
的初始化过程。
四、销毁Bean
在销毁 bean
时 spring
提供了三种扩展方式,三种扩展方式可同时使用,但不能同时指向同一个方法,多个扩展指向同一个方法这个方法也只会执行一次。
扩展方法执行顺序为:@PreDestroy
注解 -> DisposableBean
接口 -> destroy-method
参数指定。
五、测试代码
BeanProcess
实体类:
package com.nineya.spring.bean.lifecycle.entity;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Getter
@Setter
@ToString
public class BeanProcess implements BeanNameAware, ResourceLoaderAware, InitializingBean, DisposableBean {
private String name;
@PostConstruct
public void init() {
System.out.println("Bean @PostConstruct: name = " + name);
}
@PostConstruct
public void init2() {
System.out.println("Bean @PostConstruct2: name = " + name);
}
@PreDestroy
public void preDestroy() {
System.out.println("Bean @PreDestroy: name = " + name);
}
@PreDestroy
public void preDestroy2() {
System.out.println("Bean @PreDestroy2: name = " + name);
}
@Override
public void destroy() {
System.out.println("Bean DisposableBean: name = " + name);
}
@Override
public void afterPropertiesSet() {
System.out.println("Bean InitializingBean: name = " + name);
}
public void initMethod() {
System.out.println("Bean InitMethod: name = " + name);
}
public void destroyMethod() {
System.out.println("Bean DestroyMethod: name = " + name);
}
@Override
public void setBeanName(String beanName) {
System.out.println("Bean BeanNameAware: beanName = " + beanName + ", name = " + name);
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("Bean ResourceLoaderAware: resourceLoader = " + resourceLoader + ", name = " + name);
}
}
NineyaBeanFactoryPostProcessor
后置处理器:
package com.nineya.spring.bean.lifecycle.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
@Component
public class NineyaBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("后置处理器BeanFactoryPostProcessor: postProcessBeanFactory: " + String.join(",", beanFactory.getBeanDefinitionNames()));
}
}
NineyaBeanPostProcessor
后置处理器:
package com.nineya.spring.bean.lifecycle.processor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class NineyaBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器BeanPostProcessor: postProcessAfterInitialization(" + beanName + ") :" + bean);
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器BeanPostProcessor: postProcessBeforeInitialization(" + beanName + ") :" + bean);
return bean;
}
}
BeanLifecycleConfiguration
配置类:
package com.nineya.spring.bean.lifecycle.config;
import com.nineya.spring.bean.lifecycle.entity.BeanProcess;
import com.nineya.spring.bean.lifecycle.processor.NineyaBeanFactoryPostProcessor;
import com.nineya.spring.bean.lifecycle.processor.NineyaBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanLifecycleConfiguration {
@Bean(value = "test", initMethod = "initMethod", destroyMethod = "destroyMethod")
public BeanProcess beanProcess() {
BeanProcess beanProcess = new BeanProcess();
beanProcess.setName("test");
return beanProcess;
}
@Bean
public NineyaBeanPostProcessor nineyaBeanPostProcessor() {
return new NineyaBeanPostProcessor();
}
@Bean
public NineyaBeanFactoryPostProcessor nineyaBeanFactoryPostProcessor() {
return new NineyaBeanFactoryPostProcessor();
}
}
入口类:
package com.nineya.spring.bean.lifecycle;
import com.nineya.spring.bean.lifecycle.entity.BeanProcess;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanLifecycleMain {
public static void main(String[] args) {
System.out.println("## 创建容器");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
System.out.println("## 扫描Bean注解");
context.scan(BeanLifecycleMain.class.getPackage().getName());
context.refresh();
System.out.println("## 通过class取得bean");
BeanProcess beanProcess = context.getBean(BeanProcess.class);
System.out.println(beanProcess + " : " + beanProcess.hashCode());
System.out.println("## 通过bean名称取得bean");
beanProcess = (BeanProcess) context.getBean("test");
System.out.println(beanProcess + " : " + beanProcess.hashCode());
System.out.println("## 销毁Bean");
((DefaultListableBeanFactory)context.getBeanFactory()).destroySingleton("test");
System.out.println("## 取得beanDefinition");
BeanDefinition beanDefinition = context.getBeanFactory().getBeanDefinition("test");
System.out.println("beanDefinition : " + beanDefinition);
System.out.println("## 通过bean名称取得bean");
beanProcess = (BeanProcess) context.getBean("test");
System.out.println(beanProcess + " : " + beanProcess.hashCode());
}
}
执行结果可反应上述生命周期过程:
## 创建容器
## 扫描Bean注解
后置处理器BeanFactoryPostProcessor: postProcessBeanFactory: org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,beanLifecycleConfiguration,nineyaBeanFactoryPostProcessor,nineyaBeanPostProcessor,test
Bean BeanNameAware: beanName = test, name = test
Bean ResourceLoaderAware: resourceLoader = org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0, started on Tue Aug 08 15:47:54 CST 2023, name = test
后置处理器BeanPostProcessor: postProcessBeforeInitialization(test) :BeanProcess(name=test)
Bean @PostConstruct: name = test
Bean @PostConstruct2: name = test
Bean InitializingBean: name = test
Bean InitMethod: name = test
后置处理器BeanPostProcessor: postProcessAfterInitialization(test) :BeanProcess(name=test)
## 通过class取得bean
BeanProcess(name=test) : 346224929
## 通过bean名称取得bean
BeanProcess(name=test) : 346224929
## 销毁Bean
Bean @PreDestroy2: name = test
Bean @PreDestroy: name = test
Bean DisposableBean: name = test
Bean DestroyMethod: name = test
## 取得beanDefinition
beanDefinition : Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=beanLifecycleConfiguration; factoryMethodName=beanProcess; initMethodName=initMethod; destroyMethodName=destroyMethod; defined in com.nineya.spring.bean.lifecycle.config.BeanLifecycleConfiguration
## 通过bean名称取得bean
Bean BeanNameAware: beanName = test, name = test
Bean ResourceLoaderAware: resourceLoader = org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0, started on Tue Aug 08 15:47:54 CST 2023, name = test
后置处理器BeanPostProcessor: postProcessBeforeInitialization(test) :BeanProcess(name=test)
Bean @PostConstruct: name = test
Bean @PostConstruct2: name = test
Bean InitializingBean: name = test
Bean InitMethod: name = test
后置处理器BeanPostProcessor: postProcessAfterInitialization(test) :BeanProcess(name=test)
BeanProcess(name=test) : 63468833