解读spring5源码中实例化单例bean的调用链

简介: 解读spring5源码中实例化单例bean的调用链

在 Spring 5 的源码中,实例化单例 Bean 的调用链可以从 Spring Boot 的主类 SpringApplication 的 run 方法开始。

下是大致的调用链路:

1. SpringApplication.run 方法

这是 Spring Boot 应用程序启动的入口方法。它创建了一个新的 Spring 应用上下文,并启动了应用程序。

2. SpringApplication.refreshContext 方法

该方法在 run 方法内部被调用,用于完成应用上下文的初始化和刷新。

3. AbstractApplicationContext.refresh 方法

这是 Spring Framework 中 ApplicationContext 接口的实现类的方法。它负责完成应用上下文的刷新过程。

4. AbstractApplicationContext.obtainFreshBeanFactory 方法

该方法负责创建或获取新的 BeanFactory 实例,BeanFactory 是 Spring IoC 容器的核心。如果已经存在 BeanFactory 实例,则会重用。

5. AbstractApplicationContext.refreshBeanFactory 方法

该方法使用在步骤4中获取的 BeanFactory 实例进行应用上下文的配置和初始化。

6. AbstractApplicationContext.preInstantiateSingletons 方法

该方法用于预实例化所有的单例 Bean。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
  }

7. AbstractBeanFactory.preInstantiateSingletons 方法

该方法负责遍历容器中的所有 BeanDefinition,检查是否是单例模式,并执行相应的实例化操作。

8. DefaultListableBeanFactory.preInstantiateSingletons 方法

此方法继承自 AbstractBeanFactory.preInstantiateSingletons,它实际上会调用

AbstractBeanFactory.doGetBean 方法来创建单例 Bean 的实例。

  public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator var2 = beanNames.iterator();

        while(true) {
            String beanName;
            Object bean;
            do {
                while(true) {
                    RootBeanDefinition bd;
                    do {
                        do {
                            do {
                                if (!var2.hasNext()) {
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
                                        beanName = (String)var2.next();
                                        Object singletonInstance = this.getSingleton(beanName);
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
                                                AccessController.doPrivileged(() -> {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
                                                smartSingleton.afterSingletonsInstantiated();
                                            }
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());
                        } while(!bd.isSingleton());
                    } while(bd.isLazyInit());

                    if (this.isFactoryBean(beanName)) {
                        bean = this.getBean("&" + beanName);
                        break;
                    }

                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

            FactoryBean<?> factory = (FactoryBean)bean;
            boolean isEagerInit;
            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                SmartFactoryBean var10000 = (SmartFactoryBean)factory;
                ((SmartFactoryBean)factory).getClass();
                isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
            } else {
                isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
            }

            if (isEagerInit) {
                this.getBean(beanName);
            }
        }
    }

10. AbstractBeanFactory.doGetBean 方法

该方法是获取 Bean 实例的核心方法,其中包括了解决循环依赖、实例化 Bean 对象和执行初始化操作等逻辑。

11. AbstractAutowireCapableBeanFactory.createBean 方法

该方法是 AbstractBeanFactory.doGetBean 方法的一个关键步骤,用于创建 Bean 实例。它会调用相关的实例化策略和处理器来创建 Bean 对象。

12. AbstractAutowireCapableBeanFactory.instantiateBean 方法

该方法使用实例化策略(InstantiationStrategy)来实例化 Bean 对象,具体的实例化策略根据不同情况可能会有所不同。

13. SimpleInstantiationStrategy.instantiate 方法:

这是 Spring 默认的实例化策略,默认使用反射来实例化 Bean 对象。

以上是大致的调用链,详细的实现细节可能因版本和具体配置而有所不同。在整个过程中,Spring 通过调用一系列的方法和处理器,完成了单例 Bean 的实例化和初始化工作,最终将可用的单例 Bean 放入容器中供其他组件使用。

相关文章
|
14天前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
96 26
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
2月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
2月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
73 6
|
缓存 Java Spring
Spring 获取单例流程(三)
读完这篇文章你将会收获到 • Spring 何时将 bean 加入到第三级缓存和第一级缓存中 • Spring 何时回调各种 Aware 接口、BeanPostProcessor 、InitializingBean 等
134 0
|
缓存 Java Spring
Spring 获取单例流程(二)
读完这篇文章你将会收获到 • Spring 中 prototype 类型的 bean 如何做循环依赖检测 • Spring 中 singleton 类型的 bean 如何做循环依赖检测
91 0
|
XML 缓存 Java
Spring 获取单例流程(一)
读完这篇文章你将会收获到 • 在 getBean 方法中, Spring 处理别名以及 factoryBean 的 name • Spring 如何从多级缓存中根据 beanName 获取 bean • Spring 如何处理用户获取普通 bean 和 factoryBean
251 0
|
27天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
202 17
Spring Boot 两种部署到服务器的方式
|
27天前
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
59 17
springboot自动配置原理