侧胥咽 发表于 2025-6-3 00:16:09

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

生命周期流程

Spring 中的一个 Bean 从被创建到被销毁,需要经历很多个阶段的生命周期,下图是一个 Bean 从创建到销毁的生命周期流程:
https://img2024.cnblogs.com/blog/1878162/202505/1878162-20250524143115072-1228542287.png
在 Bean 的各个生命周期流程点,Spring 都提供了对应的接口或者注解,以便开发者在各个生命周期的流程点能够做一些自己的操作。
案例解析

定义 Spring 上下文工具类

Spring 中生命周期最常见的应用可能是定义一个 Spring 上下文的工具类。这个工具类也使用 @Component 注解修饰,表明它也是一个 Bean ,其次它实现了 ApplicationContextAware 接口,则说明它作为一个 Bean 被创建以及初始化的过程中需要调用 setApplicationContext() 方法,设置它所在的 Spring 上下文。代码如下:
@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() 方法加载初始数据。代码如下:
@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 注解实现原理。在上面生命周期图片中的从 XXXAware 的 setXXXAware() 方法到 postProcessAfterInitialization() 都属于初始化的这个步骤中。
在 AbstractAutowireCapableBeanFactory 中提供的 doCreateBean() 方法中提现了这三个大的步骤,其中的 createBeanInstance() 方法完成 Bean 的实例化;populateBean() 方法完成 Bean的属性填充;initializeBean() 方法完成 Bean 的初始化。代码如下:
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() 方法,代码如下:
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() 方法中调用的。代码如下:
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() 方法。代码如下:
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 注解。代码如下:
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 注解修饰的方法,然后调用的逻辑。代码如下:
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 定义中是否有自定义的初始化方法,如果有的话,则调用自定义的初始化方法。代码如下:
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() 方法。代码如下:
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;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 一个 Bean 就这样走完了它的一生之 Bean 的出生