找回密码
 立即注册
首页 业界区 业界 一个 Bean 就这样走完了它的一生之 Bean 的出生 ...

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

侧胥咽 2025-6-3 00:16:09
生命周期流程

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

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

定义 Spring 上下文工具类

Spring 中生命周期最常见的应用可能是定义一个 Spring 上下文的工具类。这个工具类也使用 @Component 注解修饰,表明它也是一个 Bean ,其次它实现了 ApplicationContextAware 接口,则说明它作为一个 Bean 被创建以及初始化的过程中需要调用 setApplicationContext() 方法,设置它所在的 Spring 上下文。代码如下:
  1. @Component
  2. public class SpringContextUtils implements ApplicationContextAware {
  3.     private static ApplicationContext applicationContext;
  4.     /**
  5.      * Spring会自动调用这个方法,注入ApplicationContext
  6.      */
  7.     @Override
  8.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  9.         SpringContextUtils.applicationContext = applicationContext;
  10.     }
  11.     /**
  12.      * 获取ApplicationContext
  13.      * @return ApplicationContext
  14.      */
  15.     public static ApplicationContext getApplicationContext() {
  16.         if (applicationContext == null) {
  17.             throw new IllegalStateException("ApplicationContext is not set. Make sure SpringContextUtils is properly initialized.");
  18.         }
  19.         return applicationContext;
  20.     }
  21.     /**
  22.      * 通过名称获取Bean
  23.      * @param name Bean的名称
  24.      * @return Bean实例
  25.      */
  26.     public static Object getBean(String name) {
  27.         return getApplicationContext().getBean(name);
  28.     }
  29.     /**
  30.      * 通过名称和类型获取Bean
  31.      * @param name Bean的名称
  32.      * @param requiredType Bean的类型
  33.      * @param <T> Bean的类型
  34.      * @return Bean实例
  35.      */
  36.     public static <T> T getBean(String name, Class<T> requiredType) {
  37.         return getApplicationContext().getBean(name, requiredType);
  38.     }
  39.     /**
  40.      * 通过类型获取Bean
  41.      * @param requiredType Bean的类型
  42.      * @param <T> Bean的类型
  43.      * @return Bean实例
  44.      */
  45.     public static <T> T getBean(Class<T> requiredType) {
  46.         return getApplicationContext().getBean(requiredType);
  47.     }
  48. }
复制代码
在 Bean 的依赖注入之后执行初始化操作

比如下面的案例中,MyService 这个 Bean 需要在它的依赖 MyRepository 这个 Bean 注入完成之后,调用依赖的 loadInitialData() 方法加载初始数据。代码如下:
  1. @Service
  2. public class MyService {
  3.     private MyRepository myRepository;
  4.    
  5.     private List<String> initialData;
  6.     @Autowired
  7.     public void setMyRepository(MyRepository myRepository) {
  8.         this.myRepository = myRepository;
  9.     }
  10.     // 依赖注入完成后执行的初始化方法
  11.     @PostConstruct
  12.     public void init() {
  13.         this.initialData = myRepository.loadInitialData();
  14.     }
  15.     public void doBusinessLogic() {
  16.     }
  17. }
  18. @Service
  19. class MyRepository {
  20.     public List<String> loadInitialData() {
  21.     }
  22. }
复制代码
@PostConstruct 注解是 JSR-250 标准定义的注解,它与 Spring 框架的耦合度比较低。除此之外还可以实现 InitializingBean 接口,在它的 afterPropertiesSet() 方法中来完成初始化;通过 XML 配置 init-method 或者 @Bean 注解的 initMethod 属性来指定任意的方法作为初始化方法来完成初始化。
Bean 创建源码解析

在 Spring 源码实现中实际上分为了三个大的步骤:实例化 -> 填充属性 -> 初始化。填充属性可以看前面的文章Spring 中@Autowired,@Resource,@Inject 注解实现原理。在上面生命周期图片中的从 XXXAware 的 setXXXAware() 方法到 postProcessAfterInitialization() 都属于初始化的这个步骤中。
在 AbstractAutowireCapableBeanFactory 中提供的 doCreateBean() 方法中提现了这三个大的步骤,其中的 createBeanInstance() 方法完成 Bean 的实例化;populateBean() 方法完成 Bean的属性填充;initializeBean() 方法完成 Bean 的初始化。代码如下:
  1. protected Object doCreateBean(String beanName, RootBeanDefinition mbd,
  2.         @Nullable Object[] args) throws BeanCreationException {
  3.     // Instantiate the bean.  
  4.     BeanWrapper instanceWrapper = null;  
  5.    
  6.     if (instanceWrapper == null) {  
  7.        //实例化Bean
  8.        instanceWrapper = createBeanInstance(beanName, mbd, args);  
  9.     }  
  10.     Object bean = instanceWrapper.getWrappedInstance();  
  11.   
  12.     // Eagerly cache singletons to be able to resolve circular references  
  13.     // even when triggered by lifecycle interfaces like BeanFactoryAware.   
  14.     boolean earlySingletonExposure = (mbd.isSingleton()
  15.             && this.allowCircularReferences
  16.             && isSingletonCurrentlyInCreation(beanName));  
  17.     if (earlySingletonExposure) {  
  18.        addSingletonFactory(beanName,
  19.                () -> getEarlyBeanReference(beanName, mbd, bean));  
  20.     }  
  21.   
  22.     // Initialize the bean instance.  
  23.     Object exposedObject = bean;  
  24.     try {  
  25.        //填充Bean的属性,比如处理@Autowired,@Resource,@Inject注解
  26.        populateBean(beanName, mbd, instanceWrapper);  
  27.       
  28.        //初始化Bean
  29.        exposedObject = initializeBean(beanName, exposedObject, mbd);  
  30.     } catch {
  31.     }
  32. }
复制代码
initializeBean()方法流程

在 initializeBean() 方法中又分为:调用 invokeAwareMethods() 方法 -> 调用 applyBeanPostProcessorsBeforeInitialization() 方法 -> 调用 invokeInitMethods() 方法 -> 调用 applyBeanPostProcessorsAfterInitialization() 方法,代码如下:
  1. protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  2.       //调用Aware()方法
  3.       invokeAwareMethods(beanName, bean);
  4.       Object wrappedBean = bean;
  5.       if (mbd == null || !mbd.isSynthetic()) {
  6.           //调用BeanPostProcessor的postProcessBeforeInitialization()方法
  7.           wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  8.       }
  9.       try {
  10.           //调用初始化方法
  11.           invokeInitMethods(beanName, wrappedBean, mbd);
  12.       }
  13.       catch (Throwable ex) {
  14.           throw new BeanCreationException(
  15.                   (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
  16.       }
  17.       if (mbd == null || !mbd.isSynthetic()) {
  18.           //调用BeanPostProcessor的postProcessAfterInitialization()方法
  19.           wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  20.       }
  21.       return wrappedBean;
  22. }
复制代码
invokeAwareMethods()方法流程

需要注意的是 invokeAwareMethods() 方法中仅仅只调用实现了 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 接口的方法。而常见的 ApplicationContextAware 接口的 setApplicationContext() 方法则是在 ApplicationContextAwareProcessor 的 postProcessBeforeInitialization() 方法中调用的。代码如下:
  1. public abstract class AbstractAutowireCapableBeanFactory {
  2.     private void invokeAwareMethods(String beanName, Object bean) {
  3.         if (bean instanceof Aware) {
  4.             if (bean instanceof BeanNameAware beanNameAware) {
  5.                 //调用setBeanName()方法
  6.                 beanNameAware.setBeanName(beanName);
  7.             }
  8.             if (bean instanceof BeanClassLoaderAware beanClassLoaderAware) {
  9.                 ClassLoader bcl = getBeanClassLoader();
  10.                 if (bcl != null) {
  11.                     //调用setBeanClassLoader()方法
  12.                     beanClassLoaderAware.setBeanClassLoader(bcl);
  13.                 }
  14.             }
  15.             if (bean instanceof BeanFactoryAware beanFactoryAware) {
  16.                 //调用setBeanFactory()方法
  17.                 beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this);
  18.             }
  19.         }
  20.     }
  21. }
  22. class ApplicationContextAwareProcessor {
  23.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  24.         if (bean instanceof Aware) {
  25.             this.invokeAwareInterfaces(bean);
  26.         }
  27.         return bean;
  28.     }
  29.     private void invokeAwareInterfaces(Object bean) {
  30.         if (bean instanceof EnvironmentAware environmentAware) {
  31.             environmentAware.setEnvironment(this.applicationContext.getEnvironment());
  32.         }
  33.         if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
  34.             embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
  35.         }
  36.         if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
  37.             resourceLoaderAware.setResourceLoader(this.applicationContext);
  38.         }
  39.         if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
  40.             applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
  41.         }
  42.         if (bean instanceof MessageSourceAware messageSourceAware) {
  43.             messageSourceAware.setMessageSource(this.applicationContext);
  44.         }
  45.         if (bean instanceof ApplicationStartupAware applicationStartupAware) {
  46.             applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
  47.         }
  48.         
  49.         if (bean instanceof ApplicationContextAware applicationContextAware) {
  50.             //这里调用的setApplicationContext()方法
  51.             applicationContextAware.setApplicationContext(this.applicationContext);
  52.         }
  53.     }
  54. }
复制代码
applyBeanPostProcessorsBeforeInitialization() 方法流程

在该方法中主要就是查找所有实现了 BeanPostProcessor 接口的对象,然后循环调用其 postProcessBeforeInitialization() 方法。代码如下:
  1. public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  2.     throws BeansException {
  3.     Object result = existingBean;
  4.     for (BeanPostProcessor processor : getBeanPostProcessors()) {
  5.         Object current = processor.postProcessBeforeInitialization(result, beanName);
  6.         if (current == null) {
  7.             return result;
  8.         }
  9.         result = current;
  10.     }
  11.     return result;
  12. }
复制代码
在 Spring 中提供了 CommonAnnotationBeanPostProcessor(@Resource 注解也是它处理的) 实现了 BeanPostProcessor 接口,在它的构造函数里面初始化了要处理 @PostConstruct 注解。代码如下:
  1. public CommonAnnotationBeanPostProcessor() {
  2.                 setOrder(Ordered.LOWEST_PRECEDENCE - 3);
  3.                 // Jakarta EE 9 set of annotations in jakarta.annotation package
  4.                 addInitAnnotationType(loadAnnotationType("jakarta.annotation.PostConstruct"));
  5.                 addDestroyAnnotationType(loadAnnotationType("jakarta.annotation.PreDestroy"));
  6.                 // Tolerate legacy JSR-250 annotations in javax.annotation package
  7.                 addInitAnnotationType(loadAnnotationType("javax.annotation.PostConstruct"));
  8.                 addDestroyAnnotationType(loadAnnotationType("javax.annotation.PreDestroy"));
  9.         }
复制代码
然后在它的子类 InitDestroyAnnotationBeanPostProcessor 的 postProcessBeforeInitialization() 实现了查找 @PostConstruct 注解修饰的方法,然后调用的逻辑。代码如下:
  1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  2.     LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  3.     try {
  4.         metadata.invokeInitMethods(bean, beanName);
  5.     }
  6.     catch (InvocationTargetException ex) {
  7.         throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
  8.     }
  9.     catch (Throwable ex) {
  10.         throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
  11.     }
  12.     return bean;
  13. }
复制代码
invokeInitMethods() 方法流程

在该方法中会先判断 Bean 是否实现了 InitializingBean 接口,如果实现了则调用其 afterPropertiesSet() 方法,然后查看 Bean 定义中是否有自定义的初始化方法,如果有的话,则调用自定义的初始化方法。代码如下:
  1. protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
  2.     throws Throwable {
  3.     boolean isInitializingBean = (bean instanceof InitializingBean);
  4.     if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
  5.         if (logger.isTraceEnabled()) {
  6.             logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
  7.         }
  8.         //调用afterPropertiesSet()方法
  9.         ((InitializingBean) bean).afterPropertiesSet();
  10.     }
  11.     if (mbd != null && bean.getClass() != NullBean.class) {
  12.         String[] initMethodNames = mbd.getInitMethodNames();
  13.         if (initMethodNames != null) {
  14.             for (String initMethodName : initMethodNames) {
  15.                 if (StringUtils.hasLength(initMethodName) &&
  16.                         !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
  17.                         !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
  18.                     //调用自定义初始化方法
  19.                     invokeCustomInitMethod(beanName, bean, mbd, initMethodName);
  20.                 }
  21.             }
  22.         }
  23.     }
  24. }
  25. protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd, String initMethodName)
  26.     throws Throwable {
  27.     Class<?> beanClass = bean.getClass();
  28.     MethodDescriptor descriptor = MethodDescriptor.create(beanName, beanClass, initMethodName);
  29.     String methodName = descriptor.methodName();
  30.     Method initMethod = (mbd.isNonPublicAccessAllowed() ?
  31.             BeanUtils.findMethod(descriptor.declaringClass(), methodName) :
  32.             ClassUtils.getMethodIfAvailable(beanClass, methodName));
  33.     //省略代码
  34.    
  35.     Method methodToInvoke = ClassUtils.getPubliclyAccessibleMethodIfPossible(initMethod, beanClass);
  36.     try {
  37.         ReflectionUtils.makeAccessible(methodToInvoke);
  38.         //这里通过反射的方式调用初始化方法
  39.         methodToInvoke.invoke(bean);
  40.     }
  41.     catch (InvocationTargetException ex) {
  42.         throw ex.getTargetException();
  43.     }
  44. }
复制代码
applyBeanPostProcessorsBeforeInitialization() 方法流程

在该方法中主要就是查找所有实现了 BeanPostProcessor 接口的对象,然后循环调用其 postProcessAfterInitialization() 方法。代码如下:
  1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  2.     LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  3.     try {
  4.         metadata.invokeInitMethods(bean, beanName);
  5.     }
  6.     catch (InvocationTargetException ex) {
  7.         throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
  8.     }
  9.     catch (Throwable ex) {
  10.         throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
  11.     }
  12.     return bean;
  13. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册