Spring中Bean实例化过程中的initializeBean方法

简介: Spring中Bean实例化过程中的initializeBean方法

populateBean方法执行后,就开始执行initializeBean方法了。在这之前前面已经完成了Bean的属性设置、依赖注入,这里属于bean初始化过程的后置部分。给用户提供一个入口,实现其他特性。


方法源码如下所示:

// AbstractAutowireCapableBeanFactory
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  // JDK安全校验机制
  if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
      invokeAwareMethods(beanName, bean);
      return null;
    }, getAccessControlContext());
  }
  else {
    invokeAwareMethods(beanName, bean);
  }
  Object wrappedBean = bean;
  // bean后置处理器的postProcessBeforeInitialization方法
  if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  }
  try {
  // 初始化方法
    invokeInitMethods(beanName, wrappedBean, mbd);
  }
  catch (Throwable ex) {
    throw new BeanCreationException(
        (mbd != null ? mbd.getResourceDescription() : null),
        beanName, "Invocation of init method failed", ex);
  }
  // bean后置处理器的postProcessAfterInitialization方法
  if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  }
  return wrappedBean;
}


如上代码所示,这里主要核心有四个步骤:invokeAwareMethods、applyBeanPostProcessorsBeforeInitialization、invokeInitMethods以及applyBeanPostProcessorsAfterInitialization。① invokeAwareMethods方法

private void invokeAwareMethods(final String beanName, final Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ClassLoader bcl = getBeanClassLoader();
      if (bcl != null) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
      }
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}


源码如上所示,其将会分别尝试触发:


((BeanNameAware) bean).setBeanName(beanName);-设置BeanName

((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);–设置Bean加载器

((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);–设置BeanFactory


② applyBeanPostProcessorsBeforeInitialization

applyBeanPostProcessorsBeforeInitialization方法会循环遍历BeanPostProcessor并调用其postProcessBeforeInitialization方法。


176df396daf24605857dddcb6bbb647a.png

如CommonAnnotationBeanPostProcessor其继承自InitDestroyAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessor接口。那么在这里就会反射调用那些被标注了@PostConstruct注解的方法,也可以看到其是在init-method方法执行前。③ invokeInitMethods

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
    throws Throwable {
// 是否为InitializingBean,也就是是否实现了InitializingBean接口
  boolean isInitializingBean = (bean instanceof InitializingBean);
  if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    if (logger.isTraceEnabled()) {
      logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    }
    if (System.getSecurityManager() != null) {
      try {
        AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
          ((InitializingBean) bean).afterPropertiesSet();
          return null;
        }, getAccessControlContext());
      }
      catch (PrivilegedActionException pae) {
        throw pae.getException();
      }
    }
    else {
    // 调用其afterPropertiesSet方法
      ((InitializingBean) bean).afterPropertiesSet();
    }
  }
  if (mbd != null && bean.getClass() != NullBean.class) {
    String initMethodName = mbd.getInitMethodName();
    if (StringUtils.hasLength(initMethodName) &&
        !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
        !mbd.isExternallyManagedInitMethod(initMethodName)) {
        // 尝试反射调用initMethod 初始化方法
      invokeCustomInitMethod(beanName, bean, mbd);
    }
  }
}


也就是说invokeInitMethods方法将会分别尝试触发:

  • ((InitializingBean) bean).afterPropertiesSet();
  • invokeCustomInitMethod(beanName, bean, mbd);


applyBeanPostProcessorsAfterInitialization

该方法会循环遍历BeanPostProcessor并调用其postProcessAfterInitialization方法。

同样以CommonAnnotationBeanPostProcessor为例,这里会触发其postProcessAfterInitialization调用,不过该处理器此时未做任何动作只是返回了bean。

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  return bean;
}


总结

在调用Bean的初始化方法之前,会调用一系列的aware接口实现,把相关的BeanName、BeanClassLoader以及BeanFactory注入到Bean中区。


接着会看到对invokeInitMethods的调用,如果Bean实现了InitializingBean的接口,会调用其afterPropertiesSet方法。


最后还会判断Bean是否配置有initMethod,如果有那么通过invokeCustomInitMethod方法 来直接调用,最终完成Bean的初始化。


关于Bean的初始化/生命周期可以参考博文:

Spring中Bean的作用域与生命周期

Spring中bean的初始化和销毁几种实现方式详解

Spring中那些BeanPostProcessor在Bean实例化过程中的作用

目录
相关文章
|
20天前
|
XML 安全 Java
|
2天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
18 6
|
4天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
31 3
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
17天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
27 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
34 1
|
2月前
|
存储 安全 Java
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
34 1
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
28 0
下一篇
DataWorks