一个 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;

}

```

相关文章
|
人工智能 JSON Java
2025 年必知的 Java 高效开发实战:10 个让代码质量飙升的黄金法则详解
《Java高效开发实战:10个让代码质量飙升的黄金法则(2025版)》聚焦现代Java开发中的关键技术实践,涵盖日志优化、响应式编程、虚拟线程、资源管理、矢量API、防御编程、空值处理、领域驱动设计、WebFlux集成及AI辅助开发等内容。通过结构化日志、Reactor并行流、Project Loom虚拟线程等技术,显著提升性能与可维护性。结合Spring WebFlux和GitHub Copilot,助力构建高性能、智能化的应用系统。本书内容已在多家头部企业验证,适合开发者逐步落地,优化代码质量与开发效率。
451 2
|
存储 安全 IDE
说一说序列化与反序列化中存在的问题
本文详细解析了Java中的序列化机制,包括序列化的概念、实现方式及应用场景。通过Student类的实例演示了对象的序列化与反序列化过程,并分析了`Serializable`接口的作用以及`serialVersionUID`的重要意义。此外,文章还探讨了如何通过自定义`readObject()`方法增强序列化的安全性,以及解决可序列化单例模式中可能产生的多实例问题。最后提供了代码示例和运行结果,帮助读者深入理解序列化的原理与实践技巧。
335 3
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
1674 8
|
人工智能 Cloud Native 安全
云原生+AI 为企业出海提供全新技术引擎!明天见
5月22日 14:00「飞天发布时刻」,阿里云云原生应用平台产品负责人李国强将重磅揭晓面向 AI 场景的云原生产品体系升级,通过弹性智能的全球一体化架构、开箱即用的云原生 AI 工程化能力,为中国企业出海提供全新技术引擎。
|
人工智能 缓存 Serverless
MCP Server 实践之旅第 3 站:MCP 协议亲和性的技术内幕
本文深入探讨了分布式架构中请求亲和性技术在Serverless范式下的实践。文章以MCP Server在函数计算平台的集成为例,剖析了基于SSE长连接通信模型的会话亲和、优雅升级等关键技术。通过双阶段协商机制与网关层协同设计,函数计算实现了MCP SSE会话亲和性保障,解决了无状态服务处理有状态请求的难题。同时,文章还展示了压测结果,验证了系统的稳定性和扩展能力,并总结了Serverless与有状态服务融合的技术创新点。
|
存储 算法 架构师
腾讯问题:有40亿整数,如何 判断一个 int 是在其中,越快越好 ?
腾讯问题:有40亿整数,如何 判断一个 int 是在其中,越快越好 ?
腾讯问题:有40亿整数,如何 判断一个 int 是在其中,越快越好 ?
|
存储 安全 中间件
Hugo博客搭建教程以及配置调优
Hugo博客搭建教程以及配置调优
621 9
|
运维 安全 持续交付
Dockerfile中小型企业实战指南
本文档旨在为中小企业提供一份 实用、易懂 的 Dockerfile 实践指南。我们深知中小企业在技术标准化、快速迭代和资源有效利用方面的需求,因此本教程将涵盖从基础概念到进阶实战的多层次 Docker 镜像构建方法,重点关注如何在有限资源下,通过规范的 Dockerfile 来提升开发、测试和部署效率。无论您是初学者还是有一定经验的开发者、运维人员,都能从中获益,快速掌握不同场景下的镜像制作和优化技巧,最终构建出 安全、高效、轻量且易于维护 的容器镜像。
429 5
|
搜索推荐 前端开发 UED
为什么建站需要响应式设计?
本文主要介绍了响应式网站的概念和优势,以及如何选择响应式设计的网站模板。响应式设计能够自动调整布局、图像和字体大小,增强用户页面浏览的体验感,提升搜索引擎的优化和排名,降低网站建设的成本。
350 1
|
人工智能 监控 JavaScript
HarmonyOS5云服务技术分享--ArkTS开发Node环境
本文详细讲解了在HarmonyOS(ArkTS API 9及以上)中使用云函数的开发技巧,结合Node.js和HTTP触发器,从零开始手把手教学。内容涵盖核心能力、开发流程(配置到部署)、高阶优化及常见问题解决,并提供实际应用场景示例。助你快速掌握Serverless开发,提升效率,探索跨端协作与AI集成等未来方向。