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实例化过程中的作用

目录
相关文章
|
8月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
518 26
|
6月前
|
缓存 安全 Java
深入解析HTTP请求方法:Spring Boot实战与最佳实践
这篇博客结合了HTTP规范、Spring Boot实现和实际工程经验,通过代码示例、对比表格和架构图等方式,系统性地讲解了不同HTTP方法的应用场景和最佳实践。
556 5
|
6月前
|
Java Spring 容器
两种Spring Boot 项目启动自动执行方法的实现方式
在Spring Boot项目启动后执行特定代码的实际应用场景中,可通过实现`ApplicationRunner`或`CommandLineRunner`接口完成初始化操作,如系统常量或配置加载。两者均支持通过`@Order`注解控制执行顺序,值越小优先级越高。区别在于参数接收方式:`CommandLineRunner`使用字符串数组,而`ApplicationRunner`采用`ApplicationArguments`对象。注意,`@Order`仅影响Bean执行顺序,不影响加载顺序。
466 2
|
8月前
|
人工智能 自然语言处理 Java
Spring 集成 DeepSeek 的 3大方法(史上最全)
DeepSeek 的 API 接口和 OpenAI 是兼容的。我们可以自定义 http client,按照 OpenAI 的rest 接口格式,去访问 DeepSeek。自定义 Client 集成DeepSeek ,可以通过以下步骤实现。步骤 1:准备工作访问 DeepSeek 的开发者平台,注册并获取 API 密钥。DeepSeek 提供了与 OpenAI 兼容的 API 端点(例如),确保你已获取正确的 API 地址。
Spring 集成 DeepSeek 的 3大方法(史上最全)
|
10月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
320 73
|
10月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
186 12
|
10月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
235 12
|
10月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
269 6
|
10月前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
430 4
|
10月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
188 1