一个 Bean 就这样走完了它的一生之 Bean 的出生

简介: 想了解 Spring 中 Bean 的销毁流程么?本文将从 Spring 源码的角度带你一步一步查看 Spring 中的 Bean 销毁时候生命周期的每个方法是如何被调用的。

## 生命周期流程

Spring 中的一个 Bean 从被创建到被销毁,需要经历很多个阶段的生命周期,下图是一个 Bean 从创建到销毁的生命周期流程:

![image.png](https://i-blog.csdnimg.cn/img_convert/e38825f2f05e29eb3b604ef31669f2bb.png)


在 Bean 的各个生命周期流程点,Spring 都提供了对应的接口或者注解,以便开发者在各个生命周期的流程点能够做一些自己的操作。


## 案例解析

### 定义 Spring 上下文工具类

Spring 中生命周期最常见的应用可能是定义一个 Spring 上下文的工具类。这个工具类也使用 `@Component` 注解修饰,表明**它也是一个 Bean** ,其次它实现了 `ApplicationContextAware` 接口,则说明它作为一个 Bean 被创建以及初始化的过程中需要调用 `setApplicationContext()` 方法,设置它所在的 Spring 上下文。代码如下:

```java

@Component

public class SpringContextUtils implements ApplicationContextAware {


   private static ApplicationContext applicationContext;


   /**

    * Spring会自动调用这个方法,注入ApplicationContext

    */

   @Override

   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

       SpringContextUtils.applicationContext = applicationContext;

   }


   /**

    * 获取ApplicationContext

    * @return ApplicationContext

    */

   public static ApplicationContext getApplicationContext() {

       if (applicationContext == null) {

           throw new IllegalStateException("ApplicationContext is not set. Make sure SpringContextUtils is properly initialized.");

       }

       return applicationContext;

   }


   /**

    * 通过名称获取Bean

    * @param name Bean的名称

    * @return Bean实例

    */

   public static Object getBean(String name) {

       return getApplicationContext().getBean(name);

   }


   /**

    * 通过名称和类型获取Bean

    * @param name Bean的名称

    * @param requiredType Bean的类型

    * @param <T> Bean的类型

    * @return Bean实例

    */

   public static <T> T getBean(String name, Class<T> requiredType) {

       return getApplicationContext().getBean(name, requiredType);

   }


   /**

    * 通过类型获取Bean

    * @param requiredType Bean的类型

    * @param <T> Bean的类型

    * @return Bean实例

    */

   public static <T> T getBean(Class<T> requiredType) {

       return getApplicationContext().getBean(requiredType);

   }

}

```

### 在 Bean 的依赖注入之后执行初始化操作

比如下面的案例中,`MyService` 这个 Bean 需要在它的依赖 `MyRepository` 这个 Bean 注入完成之后,调用依赖的 `loadInitialData()` 方法加载初始数据。代码如下:

```java

@Service

public class MyService {


   private MyRepository myRepository;

 

   private List<String> initialData;


   @Autowired

   public void setMyRepository(MyRepository myRepository) {

       this.myRepository = myRepository;

   }


   // 依赖注入完成后执行的初始化方法

   @PostConstruct

   public void init() {

       this.initialData = myRepository.loadInitialData();

   }


   public void doBusinessLogic() {

   }

}


@Service

class MyRepository {

   public List<String> loadInitialData() {

   }

}

```


`@PostConstruct` 注解是 JSR-250 标准定义的注解,它与 Spring 框架的耦合度比较低。除此之外还可以实现 `InitializingBean` 接口,在它的 `afterPropertiesSet()` 方法中来完成初始化;通过 XML 配置 `init-method` 或者 `@Bean` 注解的 `initMethod` 属性来指定任意的方法作为初始化方法来完成初始化。


## Bean 创建源码解析

在 Spring 源码实现中实际上分为了三个大的步骤:**实例化 -> 填充属性 -> 初始化**。填充属性可以看前面的文章[Spring 中@Autowired,@Resource,@Inject 注解实现原理](https://mp.weixin.qq.com/s/WVpWDU2JXFbpl-hgsywUXQ)。在上面生命周期图片中的从 `XXXAware` 的 `setXXXAware()` 方法到 `postProcessAfterInitialization()` 都属于初始化的这个步骤中。


在 `AbstractAutowireCapableBeanFactory` 中提供的 `doCreateBean()` 方法中提现了这三个大的步骤,其中的 `createBeanInstance()` 方法完成 Bean 的实例化;`populateBean()` 方法完成 Bean的属性填充;`initializeBean()` 方法完成 Bean 的初始化。代码如下:

```java

protected Object doCreateBean(String beanName, RootBeanDefinition mbd,

@Nullable Object[] args) throws BeanCreationException {

   // Instantiate the bean.  

   BeanWrapper instanceWrapper = null;  

 

   if (instanceWrapper == null) {  

      //实例化Bean

      instanceWrapper = createBeanInstance(beanName, mbd, args);  

   }  

   Object bean = instanceWrapper.getWrappedInstance();  

 

   // Eagerly cache singletons to be able to resolve circular references  

   // even when triggered by lifecycle interfaces like BeanFactoryAware.    

   boolean earlySingletonExposure = (mbd.isSingleton()

    && this.allowCircularReferences

    && isSingletonCurrentlyInCreation(beanName));  

   if (earlySingletonExposure) {  

      addSingletonFactory(beanName,

       () -> getEarlyBeanReference(beanName, mbd, bean));  

   }  

 

   // Initialize the bean instance.  

   Object exposedObject = bean;  

   try {  

      //填充Bean的属性,比如处理@Autowired,@Resource,@Inject注解

      populateBean(beanName, mbd, instanceWrapper);  

   

      //初始化Bean

      exposedObject = initializeBean(beanName, exposedObject, mbd);  

   } catch {

   }

}

```

### initializeBean()方法流程

在 `initializeBean()` 方法中又分为:**调用 invokeAwareMethods() 方法 -> 调用 applyBeanPostProcessorsBeforeInitialization() 方法 -> 调用 invokeInitMethods() 方法 -> 调用 applyBeanPostProcessorsAfterInitialization() 方法**,代码如下:

```java

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {

     //调用Aware()方法

     invokeAwareMethods(beanName, bean);


     Object wrappedBean = bean;

     if (mbd == null || !mbd.isSynthetic()) {

         //调用BeanPostProcessor的postProcessBeforeInitialization()方法

         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

     }


     try {

         //调用初始化方法

         invokeInitMethods(beanName, wrappedBean, mbd);

     }

     catch (Throwable ex) {

         throw new BeanCreationException(

                 (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);

     }

     if (mbd == null || !mbd.isSynthetic()) {

         //调用BeanPostProcessor的postProcessAfterInitialization()方法

         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

     }


     return wrappedBean;

}

```


### invokeAwareMethods()方法流程

需要注意的是 `invokeAwareMethods()` 方法中仅仅只调用实现了 `BeanNameAware`,`BeanClassLoaderAware`,`BeanFactoryAware` 接口的方法。而常见的 `ApplicationContextAware` 接口的 `setApplicationContext()` 方法则是在 `ApplicationContextAwareProcessor` 的 `postProcessBeforeInitialization()` 方法中调用的。代码如下:

```java

public abstract class AbstractAutowireCapableBeanFactory {

   private void invokeAwareMethods(String beanName, Object bean) {

       if (bean instanceof Aware) {

           if (bean instanceof BeanNameAware beanNameAware) {

               //调用setBeanName()方法

               beanNameAware.setBeanName(beanName);

           }

           if (bean instanceof BeanClassLoaderAware beanClassLoaderAware) {

               ClassLoader bcl = getBeanClassLoader();

               if (bcl != null) {

                   //调用setBeanClassLoader()方法

                   beanClassLoaderAware.setBeanClassLoader(bcl);

               }

           }

           if (bean instanceof BeanFactoryAware beanFactoryAware) {

               //调用setBeanFactory()方法

               beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this);

           }

       }

   }

}


class ApplicationContextAwareProcessor {

   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

       if (bean instanceof Aware) {

           this.invokeAwareInterfaces(bean);

       }


       return bean;

   }


   private void invokeAwareInterfaces(Object bean) {

       if (bean instanceof EnvironmentAware environmentAware) {

           environmentAware.setEnvironment(this.applicationContext.getEnvironment());

       }


       if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {

           embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);

       }


       if (bean instanceof ResourceLoaderAware resourceLoaderAware) {

           resourceLoaderAware.setResourceLoader(this.applicationContext);

       }


       if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {

           applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);

       }


       if (bean instanceof MessageSourceAware messageSourceAware) {

           messageSourceAware.setMessageSource(this.applicationContext);

       }


       if (bean instanceof ApplicationStartupAware applicationStartupAware) {

           applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());

       }

     

       if (bean instanceof ApplicationContextAware applicationContextAware) {

           //这里调用的setApplicationContext()方法

           applicationContextAware.setApplicationContext(this.applicationContext);

       }


   }

}

```


### applyBeanPostProcessorsBeforeInitialization() 方法流程

在该方法中主要就是查找所有实现了 `BeanPostProcessor` 接口的对象,然后循环调用其 `postProcessBeforeInitialization()` 方法。代码如下:

```java

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

   throws BeansException {

   Object result = existingBean;

   for (BeanPostProcessor processor : getBeanPostProcessors()) {

       Object current = processor.postProcessBeforeInitialization(result, beanName);

       if (current == null) {

           return result;

       }

       result = current;

   }

   return result;

}

```

在 Spring 中提供了 `CommonAnnotationBeanPostProcessor`(`@Resource` 注解也是它处理的) 实现了 `BeanPostProcessor` 接口,在它的构造函数里面初始化了要处理 `@PostConstruct` 注解。代码如下:

```java

public CommonAnnotationBeanPostProcessor() {

 setOrder(Ordered.LOWEST_PRECEDENCE - 3);


 // Jakarta EE 9 set of annotations in jakarta.annotation package

 addInitAnnotationType(loadAnnotationType("jakarta.annotation.PostConstruct"));

 addDestroyAnnotationType(loadAnnotationType("jakarta.annotation.PreDestroy"));


 // Tolerate legacy JSR-250 annotations in javax.annotation package

 addInitAnnotationType(loadAnnotationType("javax.annotation.PostConstruct"));

 addDestroyAnnotationType(loadAnnotationType("javax.annotation.PreDestroy"));

}

```


然后在它的子类 `InitDestroyAnnotationBeanPostProcessor` 的 `postProcessBeforeInitialization()` 实现了查找 `@PostConstruct` 注解修饰的方法,然后调用的逻辑。代码如下:

```java

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());

   try {

       metadata.invokeInitMethods(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() 方法流程

在该方法中会先判断 Bean 是否实现了 `InitializingBean` 接口,如果实现了则调用其 `afterPropertiesSet()` 方法,然后查看 Bean 定义中是否有自定义的初始化方法,如果有的话,则调用自定义的初始化方法。代码如下:

```java

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)

   throws Throwable {

   boolean isInitializingBean = (bean instanceof InitializingBean);

   if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {

       if (logger.isTraceEnabled()) {

           logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");

       }

       //调用afterPropertiesSet()方法

       ((InitializingBean) bean).afterPropertiesSet();

   }


   if (mbd != null && bean.getClass() != NullBean.class) {

       String[] initMethodNames = mbd.getInitMethodNames();

       if (initMethodNames != null) {

           for (String initMethodName : initMethodNames) {

               if (StringUtils.hasLength(initMethodName) &&

                       !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&

                       !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {

                   //调用自定义初始化方法

                   invokeCustomInitMethod(beanName, bean, mbd, initMethodName);

               }

           }

       }

   }

}



protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd, String initMethodName)

   throws Throwable {

   Class<?> beanClass = bean.getClass();

   MethodDescriptor descriptor = MethodDescriptor.create(beanName, beanClass, initMethodName);

   String methodName = descriptor.methodName();


   Method initMethod = (mbd.isNonPublicAccessAllowed() ?

           BeanUtils.findMethod(descriptor.declaringClass(), methodName) :

           ClassUtils.getMethodIfAvailable(beanClass, methodName));

   //省略代码

 

   Method methodToInvoke = ClassUtils.getPubliclyAccessibleMethodIfPossible(initMethod, beanClass);


   try {

       ReflectionUtils.makeAccessible(methodToInvoke);

       //这里通过反射的方式调用初始化方法

       methodToInvoke.invoke(bean);

   }

   catch (InvocationTargetException ex) {

       throw ex.getTargetException();

   }

}

```


### applyBeanPostProcessorsBeforeInitialization() 方法流程

在该方法中主要就是查找所有实现了 `BeanPostProcessor` 接口的对象,然后循环调用其 `postProcessAfterInitialization()` 方法。代码如下:

```java

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());

   try {

       metadata.invokeInitMethods(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;

}

```

相关文章
|
2月前
|
人工智能 运维 监控
OpenClaw是什么能干什么 新版OpenClaw完整入门教程 核心功能与阿里云部署实操指南
在AI智能体全面普及的2026年,各类自动化代理工具层出不穷,OpenClaw凭借开源免费、私有化部署、多平台适配、强大任务执行能力迅速走红,成为个人办公、团队协作、开发运维、消息自动交互的热门选择。很多新手初次接触OpenClaw时,都不清楚它到底是什么、具备哪些核心能力、适合什么场景,也不知道如何在阿里云服务器上快速完成部署配置。
431 3
|
8月前
|
弹性计算 人工智能 安全
Alibaba cloud linux镜像操作系统怎么样?基于ECS深度优化的Linux操作系统全解析
Alibaba Cloud Linux是阿里云自研的免费Linux操作系统,兼容CentOS/RHEL生态,专为云服务器ECS优化,支持Web、云原生、AI等多种场景。提供十年免费维护、内核热补丁、多架构支持及安全加固,性能卓越,开箱即用,助力用户高效稳定上云。
|
8月前
|
数据库
【阿里云Data+AI 创新融合交流会—成都站】Workshop活动来袭!
诚邀您参加阿里云数据库Data+AI交流会——成都站!2025年12月9日,共探行业实战与未来机遇,现场参与即有机会领取限量版精美羽绒服,先到先得!点击链接或扫码报名,席位有限,立即锁定参会资格!
574 1
|
4月前
|
数据采集 IDE 编译器
基于51单片机的串口(RS232+485)通信程序设计
基于STC89C52RC单片机(8位,11.0592MHz晶振),实现RS232全双工通信与RS485半双工通信双模式。系统通过UART串口连接MAX232(RS232电平转换)和MAX485(RS485差分转换),支持双机通信(点对点)与总线通信(多点),具备数据收发、帧格式自定义、收发切换控制功能,适用于工业控制、仪器仪表通信等场景。
|
8月前
|
缓存 监控 算法
PHP 8的JIT编译器:性能提升的利器
PHP 8的JIT编译器:性能提升的利器
501 129
|
12月前
|
安全 Java
Java中的Switch表达式:更简洁的多路分支
Java中的Switch表达式:更简洁的多路分支
783 211
|
人工智能 Cloud Native 安全
云原生+AI 为企业出海提供全新技术引擎!明天见
5月22日 14:00「飞天发布时刻」,阿里云云原生应用平台产品负责人李国强将重磅揭晓面向 AI 场景的云原生产品体系升级,通过弹性智能的全球一体化架构、开箱即用的云原生 AI 工程化能力,为中国企业出海提供全新技术引擎。
|
人工智能 缓存 Serverless
MCP Server 实践之旅第 3 站:MCP 协议亲和性的技术内幕
本文深入探讨了分布式架构中请求亲和性技术在Serverless范式下的实践。文章以MCP Server在函数计算平台的集成为例,剖析了基于SSE长连接通信模型的会话亲和、优雅升级等关键技术。通过双阶段协商机制与网关层协同设计,函数计算实现了MCP SSE会话亲和性保障,解决了无状态服务处理有状态请求的难题。同时,文章还展示了压测结果,验证了系统的稳定性和扩展能力,并总结了Serverless与有状态服务融合的技术创新点。
IDEA修改JDK版本
在IDEA中修改项目JDK版本的方法如下:1. 右键点击项目;2. 选择“Open Module Settings”,如图所示;3. 在弹出窗口中配置自定义的JDK路径。通过以上步骤,可轻松更改项目所使用的JDK版本,满足不同开发环境的需求。
4067 65
|
JSON 监控 Java
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
日志与追踪的完美融合:OpenTelemetry MDC 实践指南
1114 24