其他阶段的解析参考:
总体概括
逻辑位于
initializeBean方法中,它是Sping Bean生命周期中初始化阶段的核心方法:
- 它先确保了Bean在完全初始化前,可以获得必要的容器信息(通过执行
Aware接口方法); - 然后会按照顺序执行初始化方法的回调(顺序为
@PostConstruct注解、InitializingBean接口实现和init-method); - 最后,Bean被完全初始化,并可能被后置处理器包装(如AOP代理),然后返回给容器,准备被使用。
源码位置
接依赖注入过程,初始化的代码也是在
AbstractAutowireCapableBeanFactory的doCreateBean方法中,紧接着依赖注入
源码位置,initializeBean方法是处理Bean初始化的:
java
//.................
Object exposedObject = bean;
try {
// 依赖注入
populateBean(beanName, mbd, instanceWrapper);
// 执行初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//.................
try {
// 注册销毁处理
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
进入
initializeBean
这个方法负责初始化Bean实例,包括调用Aware接口、BeanPostProcessor的前置和后置处理以及自定义的初始化方法。
方法参数:
-
beanName: Bean的名称 -
bean: 已经实例化并填充属性后的Bean实例 -
mbd: 合并后的Bean定义(RootBeanDefinition),可能为null
步骤概括,initializeBean中会按顺序执行如下方法:
- invokeAwareMethods 方法:执行
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware等基础的Aware回调,向 Bean 注入基础环境信息,允许Bean获取底层资源 - applyBeanPostProcessorsBeforeInitialization 方法:调用所有
BeanPostProcessor处理器的postProcessBeforeInitialization方法,用来执行@PostConstruct注解标注的Bean的初始化方法 ,并进行ApplicationContext等相关的的高级Aware回调(依赖于前面的基础Aware) - invokeInitMethods 方法:执行其他初始化方法。如果Bean实现了
InitializingBean接口,则执行重写的afterPropertiesSet方法进行初始化,如果Bean还有有init-method,再执行init-method的初始化方法 - applyBeanPostProcessorsAfterInitialization 方法:调用
BeanPostProcessor处理器的postProcessAfterInitialization方法,做初始化后置处理,主要是创建代理对象,并将实现了ApplicationListener接口的bean注册为事件监听器等
下面是源码分析:
java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 如果用了安全管理器,在特权块中执行Aware,否则直接执行,作用:在安全上下文环境下调用 Aware 接口
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 调用当前Bean实现了`Aware`接口的方法,如果当前Bean实现了`Aware`接口,并且其类型满足下面三种任一,则执行对应方法:
// BeanNameAware:设置Bean的名称
// BeanClassLoaderAware:设置类加载器
// BeanFactoryAware:设置BeanFactory
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
// 如果Bean定义为空或Bean不是合成(spring自身生成的)的,则应用BeanPostProcessor的前置初始化方法
if (mbd == null || !mbd.isSynthetic()) {
// 调用处理器执行`@PostConstruct`注解的初始化方法
// 即:遍历所有BeanPostProcessor处理器,调用其postProcessBeforeInitialization方法
// 如果某个处理器返回null,则不再执行后面剩余的BeanPostProcessor,直接将上一个BeanPostProcessor处理后的bean对象返回
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 负责调用Bean的其他初始化方法。具体包括:
// 如果Bean实现了`InitializingBean`接口,调用其`afterPropertiesSet()`方法。
// 调用Bean定义中指定的自定义初始化方法(通过`init-method`属性或@PostConstruct注解等指定)。
// 异常处理:如果初始化方法抛出异常,则包装为`BeanCreationException`。
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 应用BeanPostProcessor的后置初始化方法
if (mbd == null || !mbd.isSynthetic()) {
// 遍历所有BeanPostProcessor调用其postProcessAfterInitialization方法。同样,如果某个处理器返回null,则中断。
// 这个阶段是Bean初始化后的最后处理,常用于生成代理对象(如AOP代理)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
// 返回经过所有处理的Bean,可能是原始Bean,也可能是被BeanPostProcessor包装后的Bean(例如代理对象)。
return wrappedBean;
}
处理过程
1.调用Aware
作用: 在Bean初始化阶段向 Bean 注入基础环境信息,允许Bean感知并访问容器的底层资源
进入
invokeAwareMethods方法中:
java
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
// 如果bean实现了BeanNameAware。调用setBeanName方法--注入bean的名称
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 如果bean实现了BeanClassLoaderAware。调用setBeanClassLoader方法注入当前的ClassLoader类加载器
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// 如果bean实现了BeanFactoryAware,调用setBeanFactory方法--注入BeanFactory
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
依次看三个Aware的实现
BeanNameAware
作用: 如果该Bean实现了BeanNameAware,则向 Bean 注入其在 Spring 容器中的 唯一标识符,即Bean id,这里也算Bean名称。
应用实例
- 日志记录:在日志中输出当前 Bean 的名称
java
public class MyBean implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name; // 接收容器注入的名称
System.out.println("Bean name set: " + beanName);
}
}
BeanClassLoaderAware
作用 :为 Bean 提供加载其class字节码的 类加载器 (ClassLoader)。
关键用途:
- 动态加载类:运行时通过
ClassLoader加载外部资源或类 - 反射操作:需明确类加载器以避免
ClassNotFoundException - 代理生成:AOP 代理类需依赖原始类的类加载器
示例:
java
public class CustomLoaderBean implements BeanClassLoaderAware {
private ClassLoader loader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.loader = classLoader;
// 示例:动态加载配置类
Class<?> configClass = loader.loadClass("com.example.Config");
}
}
BeanClassLoaderAware
-
作用 :
将 BeanFactory 容器实例 注入到 Bean 中,使 Bean 能直接操作容器。
-
使用扩展:
- 手动获取其他 Bean:通过
beanFactory.getBean()动态查找依赖 - 检查 Bean 作用域:判断 Bean 是单例还是原型
- 访问容器级服务:如解析 SpEL 表达式、获取环境变量等
- 手动获取其他 Bean:通过
-
注意事项:
避免在
setBeanFactory()中直接调用getBean(),可能导致循环依赖问题。javapublic class ContainerAwareBean implements BeanFactoryAware { private BeanFactory beanFactory; @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; // 示例:检查某个 Bean 的作用域 boolean isSingleton = beanFactory.isSingleton("otherBean"); } }
对比总结
| 接口 | 注入内容 | 主要用途 | 使用频率 |
|---|---|---|---|
BeanNameAware |
Bean 在容器中的名称 | 日志标识、动态逻辑分支 | ★★★☆☆ |
BeanClassLoaderAware |
加载当前 Bean 的类加载器 | 动态类加载、反射、代理生成 | ★★☆☆☆ |
BeanFactoryAware |
BeanFactory 实例 |
手动获取 Bean、检查作用域、容器级操作 | ★★★★☆ |
2.applyBeanPostProcessorsBeforeInitialization
遍历所有的
BeanPostProcessor处理器,调用其postProcessBeforeInitialization方法,做初始化前置处理
java
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 依次执行容器中所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
// 如果处理完的结果返回 null ,则不再执行后面剩余的 BeanPostProcessor ,
// 而是直接将上一个 BeanPostProcessor 处理之后的 bean 对象返回。
if (current == null) {
return result;
}
result = current;
}
return result;
}
依次看BeanPostProcessor的几个重要实现:
InitDestroyAnnotationBeanPostProcessor
InitDestroyAnnotationBeanPostProcessor处理器的postProcessBeforeInitialization方法作用:调用 @PostConstruct 标注的初始化方法
在上面介绍MergedBeanDefinitionPostProcessor时,已经讲解过findLifecycleMetadata方法,它可以把标注了 @PostConstruct 和 @PreDestroy 注解的方法都取出来,此处获取的也正是在之前调用MergedBeanDefinitionPostProcessor时缓存的:
java
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 收集Bean中被@PostConstruct和@PreDestroy注解标记的方法,封装为元数据
// 之前在执行`MergedBeanDefinitionPostProcessor`已经收集过,这里可以直接取到
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 通过获取到的元数据来执行@PostConstruct标记的初始化方法
metadata.c(bean, beanName);
}catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
进入invokeInitMethods
java
public void invokeInitMethods(Object target, String beanName) throws Throwable {
Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
// this.initMethods代表@PostConstruct标记的初始化方法
Collection<LifecycleElement> initMethodsToIterate =
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
if (!initMethodsToIterate.isEmpty()) {
for (LifecycleElement element : initMethodsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
}
// 反射执行初始化方法
element.invoke(target);
}
}
}
element.invoke内部使用反射执行,需要注意的是关于 @PostConstruct 和 @PreDestroy 注解的使用,被其标记的方法可以使用任意访问修饰符,但一定不能有方法参数。
java
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target, (Object[]) null);
}
ApplicationContextAwareProcessor
用于执行ApplicationContext的回调,进入此处理器的postProcessBeforeInitialization方法,内部用于其他7种Aware接口的回调,作用与上面回调Aware接口的作用相同,都是为Bean提供容器资源,让Bean在初始化阶段获取Spring容器中的特定资源或服务来执行特别操作。
下面看其实现代码:
java
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 如果Bean没有实现以下类型的Aware接口则直接结束此方法
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
AccessControlContext acc = null;
// 设置安全上下文
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
// 在安全环境下执行Aware接口
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
// 直接执行Aware接口
invokeAwareInterfaces(bean);
}
return bean;
}
简单介绍下调用的7个实现:
- EnvironmentAware :调用
setEnvironment方法,注入Spring应用的环境配置Environment对象,用于访问配置属性,读取系统环境变量、JVM参数等 - EmbeddedValueResolverAware :调用
setEmbeddedValueResolver方法,注入字符串占位符解析器StringValueResolver,用于解析${...}(属性占位符)和#{...}(SpEL表达式),动态替换配置文件中的变量值 - ResourceLoaderAware :调用
setResourceLoader方法,注入资源加载器ResourceLoader,用于加载类路径、文件系统、URL网络资源等 - ApplicationEventPublisherAware :调用
setApplicationEventPublisher方法,注入事件发布器ApplicationEventPublisher,用于发布继承ApplicationEvent的自定义应用事件 - MessageSourceAware :调用
setMessageSource方法,注入MessageSource,用于支持国际化资源处理。 - ApplicationContextAware :调用
setApplicationContext方法,注入Spring上下文容器ApplicationContext,可用于获取容器中的其他Bean、或访问其他容器级功能(如注册Bean定义、获取环境变量) - ApplicationStartupAware :调用
setApplicationStartup方法,注入应用启动指标收集器ApplicationStartup,用于记录启动阶段耗时(如Bean初始化、PostProcessor处理),来进行性能分析及启动优化
思考一个问题, 为什么是先通过invokeAwareMethods方法进行BeanNameAware、BeanClassLoaderAware、BeanClassLoaderAware的回调,然后才是使用applyBeanPostProcessorsBeforeInitialization方法进行ApplicationContextAware等另外几个Aware实现的回调呢?这里总结原因有两个:
-
执行顺序的必要性:
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware提供容器最底层的元信息,其他Aware接口依赖这些基础能力,因此必须先设置基础的Aware,再设置更高级的。比如:
ApplicationContextAware需通过BeanFactory获取容器引用;
EmbeddedValueResolverAware依赖BeanFactory解析占位符;
ResourceLoaderAware需类加载器加载资源; -
避免循环依赖问题:
BeanFactoryAware的注入在BeanPostProcessor执行之前完成,这样在BeanPostProcessor中如果需要使用BeanFactory(例如获取其他bean),可以避免循环依赖问题。
因此可知额外一点:BeanFactory 的注入时机比 ApplicationContext 早。
3.invokeInitMethods
该方法负责调用bean的初始化方法。它主要处理两种初始化方法:
-
实现
InitializingBean接口的afterPropertiesSet初始化方法。 -
在bean定义中通过
init-method指定的自定义初始化方法。
invokeInitMethods方法
方法内部主要执行了两个操作:
- 先通过
afterPropertiesSet方法执行InitializingBean接口的初始化 - 然后通过
invokeCustomInitMethod方法执行init-method的初始化。
下面是invokeInitMethods方法源码,正是此处源码,决定了三种Bean初始化方式执行先后顺序是:
@PostConstruct→InitializingBean接口 →init-method
java
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 检查Bean是否实现了InitializingBean接口
boolean isInitializingBean = (bean instanceof InitializingBean);
// Bean实现了InitializingBean接口,且没有外部管理的afterPropertiesSet方法(避免重复执行)时,条件为true
// 外部管理是有些bean可能由其他框架管理或其他整合类库管理,Spring不调用它们的生命周期方法,以避免重复执行
if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
// 在有安全管理器环境下使用特权方式执行afterPropertiesSet
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 直接执行afterPropertiesSet
((InitializingBean) bean).afterPropertiesSet();
}
}
// BeanDefinition非空,且Bean不NullBean则条件成立
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
// 同时满足如下三个条件,则调用init-method指定的初始化方法
// 存在init方法名称、不是afterPropertiesSet方法(避免重复,上面已经调用了)、没有外部管理该方法
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
// 执行init-method
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
afterPropertiesSet方法,执行通过InitializingBean接口实现的初始化
afterPropertiesSet方法来自于InitializingBean接口:
java
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
我们的Bean可以实现InitializingBean接口并重写其afterPropertiesSet方法,当Bean进行初始化并执行到invokeInitMethods时,就会执行该Bean自定义的初始化方法,举例:
java
@Component
public class TestBean implements InitializingBean {
private Integer number;
//初始化方法
@Override
public void afterPropertiesSet() throws Exception {
this.ink = 1;
System.out.println("自定义初始化方法执行,编号为"+number);
}
}
invokeCustomInitMethod方法,执行init-method的初始化
init-method的使用方式:
java
@Bean(initMethod = "初始化方法名", destroyMethod = "销毁方法名")
方法逻辑概括:
- 方法查找:使用反射获取初始化方法
- 访问权限:确保方法可访问(即使是 private 方法)
- 方法调用:通过反射执行初始化方法
java
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
throws Throwable {
//.............省略
// 安全环境下反射执行
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(methodToInvoke);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> methodToInvoke.invoke(bean), getAccessControlContext());
}
catch (PrivilegedActionException pae) {
InvocationTargetException ex = (InvocationTargetException) pae.getException();
throw ex.getTargetException();
}
}
else {
try {
// 直接执行
ReflectionUtils.makeAccessible(methodToInvoke);
methodToInvoke.invoke(bean);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
4.applyBeanPostProcessorsAfterInitialization
遍历所有的
BeanPostProcessor处理器,调用其postProcessAfterInitialization方法,做初始化后置处理
与前面postProcessBeforeInitialization方法的逻辑一致
java
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 依次执行容器中所有 BeanPostProcessor 的 postProcessAfterInitialization 方法
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
// 如果处理完的结果返回 null ,则不再执行后面剩余的 BeanPostProcessor ,
// 而是直接将上一个 BeanPostProcessor 处理之后的 bean 对象返回。
if (current == null) {
return result;
}
result = current;
}
return result;
}
下面看几个后置处理的重要实现
AbstractAutoProxyCreator
它实现了BeanPostProcessor接口的postProcessAfterInitialization方法,用于在Bean初始化后创建代理对象 ,它也是 AOP 创建代理对象的核心实现。它会检查当前Bean是否需要被代理,如果需要,则创建代理对象。
AbstractAutoProxyCreator重写的postProcessAfterInitialization方法源码如下:
java
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 生成当前bean的缓存key(通常是beanName和bean的Class的组合)
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 根据缓存key从早期引用中移除当前bean,如果移除的不是当前Bean,则生成代理
// 此操作是为了避免重复代理,在Spring解决循环依赖时,可能会提前暴露一个代理对象(前面的getEarlyBeanReference方法)
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 生成并返回代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
它会进行一个判断:如果这个bean在早期被代理过(即为了解决循环依赖而提前暴露代理),并且当时存入的原始bean就是当前这个bean,那么我们就跳过代理(因为代理已经在早期创建了,并且已经放入容器中了),否则就进行代理。
ApplicationListenerDetector
这个后处理器的作用是检测那些实现了 ApplicationListener 接口的bean,并将它们注册为应用事件监听器。
java
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 判断当前bean是否实现了ApplicationListener接口
if (bean instanceof ApplicationListener) {
// 判断当前Bean是否为单实例的Bean
Boolean flag = this.singletonNames.get(beanName);
// 如果当前Bean是单例bean,直接将其注册到应用上下文的监听器列表中
if (Boolean.TRUE.equals(flag)) {
// 向 ApplicationContext 中注册监听器
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
// 如果不是单实例Bean,记录日志,并从singletonNames映射中移除该bean数据(因为非单例不需要被注册)
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
"but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed " +
"to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
// 无论是否处理了监听器,最终都原样返回bean实例
return bean;
}
注册销毁处理
即如下代码的registerDisposableBeanIfNecessary方法
java
//.................
Object exposedObject = bean;
try {
// 依赖注入
populateBean(beanName, mbd, instanceWrapper);
// 执行初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//.................
try {
// 注册销毁处理
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
作用: 此方法会检查Bean是否有销毁逻辑,如果有则将Bean封装为
DisposableBeanAdapter对象并缓存起来,用于后续在Bean销毁时阶段执行其销毁逻辑
Bean是否有销毁逻辑的判断条件:
- 是否声明了
@PreDestroy注解 - 是否实现了
DisposableBean接口 - 是否声明了
destroy-method方法
进入
registerDisposableBeanIfNecessary:
根据Bean作用域的不同走不同的分支,但最后都是封装为DisposableBeanAdapter对象,后续会使用该对象进行销毁回调, DisposableBeanAdapter用于执行如下3种销毁方法:
- 所有
DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,它是对应@PreDestroy注解的处理 - 实现了
DisposableBean的Bean重写的destroy - 通过
destroy-method指定的自定义销毁方法
java
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
// 如果启用了安全管理器,则获取访问控制上下文AccessControlContext,否则为null
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
// 需满足两个条件才会注册
// 1.Bean的作用域不是原型,因为原型Bean不会在容器销毁时被销毁,所以不需要注册
// 2.判断Bean是否需要销毁。requiresDestruction会判断Bean是否实现了`DisposableBean`接口、定义了自定义的销毁方法,或有`DestructionAwareBeanPostProcessor`需要处理
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
// 单例Bean的销毁注册
if (mbd.isSingleton()) {
// 将单例Bean封装为DisposableBeanAdapter,并存入disposableBeans(LinkedHashMap)中,后续来执行销毁
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
// 处理非单例且非原型的其他作用域,
else {
// 先获取作用域
Scope scope = this.scopes.get(mbd.getScope());
// 找不到对应的作用域,抛出异常
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
// 向该作用域注册销毁回调。当作用域生命周期结束时进行回调。这里同样使用DisposableBeanAdapter封装销毁逻辑
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
扩展,Bean销毁的执行时机
-
单例Bean :在容器关闭时(
AbstractApplicationContext.close()),会调用每个单例Bean的销毁方法。 -
自定义作用域Bean:在作用域生命周期结束时,由作用域对象负责触发销毁回调。