Bean生命周期初始化阶段

其他阶段的解析参考:

总体概括

逻辑位于initializeBean方法中,它是Sping Bean生命周期中初始化阶段的核心方法:

  1. 它先确保了Bean在完全初始化前,可以获得必要的容器信息(通过执行Aware接口方法);
  2. 然后会按照顺序执行初始化方法的回调(顺序为@PostConstruct注解、InitializingBean接口实现和init-method);
  3. 最后,Bean被完全初始化,并可能被后置处理器包装(如AOP代理),然后返回给容器,准备被使用。

源码位置

接依赖注入过程,初始化的代码也是在AbstractAutowireCapableBeanFactorydoCreateBean方法中,紧接着依赖注入

源码位置,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中会按顺序执行如下方法:

  1. invokeAwareMethods 方法:执行BeanNameAwareBeanClassLoaderAwareBeanFactoryAware等基础的Aware回调,向 Bean 注入基础环境信息,允许Bean获取底层资源
  2. applyBeanPostProcessorsBeforeInitialization 方法:调用所有BeanPostProcessor处理器的postProcessBeforeInitialization方法,用来执行@PostConstruct注解标注的Bean的初始化方法 ,并进行ApplicationContext等相关的的高级Aware回调(依赖于前面的基础Aware)
  3. invokeInitMethods 方法:执行其他初始化方法。如果Bean实现了InitializingBean接口,则执行重写的afterPropertiesSet方法进行初始化,如果Bean还有有init-method,再执行init-method的初始化方法
  4. 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 表达式、获取环境变量等
  • 注意事项:

    避免在 setBeanFactory() 中直接调用 getBean(),可能导致循环依赖问题。

    java 复制代码
    public 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个实现:

  1. EnvironmentAware :调用setEnvironment方法,注入Spring应用的环境配置Environment对象,用于访问配置属性,读取系统环境变量、JVM参数等
  2. EmbeddedValueResolverAware :调用setEmbeddedValueResolver方法,注入字符串占位符解析器StringValueResolver,用于解析${...}(属性占位符)和#{...}(SpEL表达式),动态替换配置文件中的变量值
  3. ResourceLoaderAware :调用setResourceLoader方法,注入资源加载器ResourceLoader,用于加载类路径、文件系统、URL网络资源等
  4. ApplicationEventPublisherAware :调用setApplicationEventPublisher方法,注入事件发布器ApplicationEventPublisher,用于发布继承ApplicationEvent的自定义应用事件
  5. MessageSourceAware :调用setMessageSource方法,注入MessageSource,用于支持国际化资源处理。
  6. ApplicationContextAware :调用setApplicationContext方法,注入Spring上下文容器ApplicationContext,可用于获取容器中的其他Bean、或访问其他容器级功能(如注册Bean定义、获取环境变量)
  7. ApplicationStartupAware :调用setApplicationStartup方法,注入应用启动指标收集器ApplicationStartup,用于记录启动阶段耗时(如Bean初始化、PostProcessor处理),来进行性能分析及启动优化

思考一个问题, 为什么是先通过invokeAwareMethods方法进行BeanNameAwareBeanClassLoaderAwareBeanClassLoaderAware的回调,然后才是使用applyBeanPostProcessorsBeforeInitialization方法进行ApplicationContextAware等另外几个Aware实现的回调呢?这里总结原因有两个:

  1. 执行顺序的必要性:

    BeanNameAwareBeanClassLoaderAwareBeanFactoryAware提供容器最底层的元信息,其他Aware接口依赖这些基础能力,因此必须先设置基础的Aware,再设置更高级的。比如:

    ApplicationContextAware需通过BeanFactory获取容器引用;

    EmbeddedValueResolverAware依赖BeanFactory解析占位符;

    ResourceLoaderAware需类加载器加载资源;

  2. 避免循环依赖问题:

    BeanFactoryAware的注入在BeanPostProcessor执行之前完成,这样在BeanPostProcessor中如果需要使用BeanFactory(例如获取其他bean),可以避免循环依赖问题。

因此可知额外一点:BeanFactory 的注入时机比 ApplicationContext 早。


3.invokeInitMethods

该方法负责调用bean的初始化方法。它主要处理两种初始化方法:

  1. 实现InitializingBean接口的afterPropertiesSet初始化方法。

  2. 在bean定义中通过init-method指定的自定义初始化方法。

invokeInitMethods方法

方法内部主要执行了两个操作:

  1. 先通过afterPropertiesSet方法执行InitializingBean接口的初始化
  2. 然后通过invokeCustomInitMethod方法执行init-method的初始化。

下面是invokeInitMethods方法源码,正是此处源码,决定了三种Bean初始化方式执行先后顺序是:

  • @PostConstructInitializingBean 接口 → 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 = "销毁方法名")

方法逻辑概括:

  1. 方法查找:使用反射获取初始化方法
  2. 访问权限:确保方法可访问(即使是 private 方法)
  3. 方法调用:通过反射执行初始化方法
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是否有销毁逻辑的判断条件:

  1. 是否声明了 @PreDestroy 注解
  2. 是否实现了 DisposableBean 接口
  3. 是否声明了 destroy-method 方法

进入registerDisposableBeanIfNecessary

根据Bean作用域的不同走不同的分支,但最后都是封装为DisposableBeanAdapter对象,后续会使用该对象进行销毁回调, DisposableBeanAdapter用于执行如下3种销毁方法:

  1. 所有DestructionAwareBeanPostProcessorpostProcessBeforeDestruction方法,它是对应@PreDestroy注解的处理
  2. 实现了DisposableBean的Bean重写的destroy
  3. 通过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:在作用域生命周期结束时,由作用域对象负责触发销毁回调。

相关推荐
爱笑的源码基地2 小时前
基于Java+Spring Boot、Vue的B/S医院患者随访管理系统源码,支持二次开发,三级随访体系(出院/门诊随访)、智慧云库(表单配置)
java·vue.js·spring boot·源码·程序代码·随访系统·诊后回访
ashane13143 小时前
Springboot 启动过程及源码分析
java·spring boot·后端
后端小张3 小时前
【JAVA进阶】SpringBoot启动流程深度解析:从main方法到应用就绪的完整旅程
java·spring boot·后端·spring·spring cloud·java-ee·流程分析
程序员buddha10 小时前
springboot-mvc项目示例代码
java·spring boot·mvc
sg_knight12 小时前
Docker 实战:如何限制容器的内存使用大小
java·spring boot·spring·spring cloud·docker·容器·eureka
小马爱打代码12 小时前
Spring Boot 3 :实现分布式追踪
spring boot·分布式·microsoft
serendipity_hky12 小时前
【微服务 - easy视频 | day03】服务与服务之间的调用
spring boot·spring cloud·微服务·架构
烤麻辣烫15 小时前
黑马程序员苍穹外卖(新手)Day1
java·数据库·spring boot·学习·mybatis
Mr. bigworth16 小时前
三级缓存解决循环依赖的原理
spring boot