IOC容器初始化过程中单例Bean的预实例化

简介: IOC容器初始化过程中单例Bean的预实例化

在容器的refresh方法中我们可以看到finishBeanFactoryInitialization方法,该方法就是实例化所有非懒加载实例


2ef69b46ca234789afae30476f546451.png


b06d25f96aac4597b1510be24b0bdca8.png

① finishBeanFactoryInitialization

AbstractApplicationContext的finishBeanFactoryInitialization方法封装了对lazy-init属性的处理,实际处理部分是在DefaultListableBeanFactory的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();
}

② preInstantiateSingletons

这里获取所有的beanDefinitionNames,如果其非抽象、是单例、未配置lazy_init属性或其值非true那么就会触发getBean的操作。比如前面图片中我们的swiperController就是在这里被实例化的。

@Override
public void preInstantiateSingletons() throws BeansException {
  if (logger.isTraceEnabled()) {
    logger.trace("Pre-instantiating singletons in " + this);
  }
  // Iterate over a copy to allow for init methods which in turn register new bean definitions.
  // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  // Trigger initialization of all non-lazy singleton beans...
  for (String beanName : beanNames) {
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
      if (isFactoryBean(beanName)) {
        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        if (bean instanceof FactoryBean) {
          final FactoryBean<?> factory = (FactoryBean<?>) bean;
          boolean isEagerInit;
          if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                    ((SmartFactoryBean<?>) factory)::isEagerInit,
                getAccessControlContext());
          }
          else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                ((SmartFactoryBean<?>) factory).isEagerInit());
          }
          if (isEagerInit) {
            getBean(beanName);
          }
        }
      }
      else {
        getBean(beanName);
      }
    }
  }
  // Trigger post-initialization callback for all applicable beans...
  for (String beanName : beanNames) {
    Object singletonInstance = getSingleton(beanName);
    if (singletonInstance instanceof SmartInitializingSingleton) {
      final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
      if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
          smartSingleton.afterSingletonsInstantiated();
          return null;
        }, getAccessControlContext());
      }
      else {
        smartSingleton.afterSingletonsInstantiated();
      }
    }
  }
}

方法解释如下:

  • ① 拿到所有的beanDefinitionNames
  • ② 遍历beanNames,其非抽象、是单例、未配置lazy_init属性或其值非true那么就会触发getBean的操作;
  • ③ 遍历上面预实例化的单例bean,判断是否为SmartInitializingSingleton ;如果是,则调用其afterSingletonsInstantiated方法。

SmartInitializingSingleton提供一个在所有Bean都创建后才调用的初始化方法afterSingletonsInstantiated。与InitializingBean区别是其被触发的时机在所有单例bean都被实例化后,才会逐个触发SmartInitializingSingleton的afterSingletonsInstantiated方法。


目录
相关文章
|
1月前
|
Java 测试技术 开发工具
ApplicationArguments读取应用程序参数并注入到IOC容器
ApplicationArguments读取应用程序参数并注入到IOC容器
ApplicationArguments读取应用程序参数并注入到IOC容器
|
2月前
|
XML Java 数据格式
Spring IoC容器初始化过程(xml形式)
Spring IoC容器初始化过程(xml形式)
46 0
|
1月前
|
Java 数据库连接 Spring
|
1月前
|
存储 前端开发 Java
springboot中的第二个IOC容器BootstrapContext
springboot中的第二个IOC容器BootstrapContext
springboot中的第二个IOC容器BootstrapContext
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
|
3天前
|
存储 Kubernetes Docker
Kubernetes(K8S)集群管理Docker容器(概念篇)
Kubernetes(K8S)集群管理Docker容器(概念篇)
|
3天前
|
存储 Ubuntu 安全
Docker容器常用命令
Docker容器常用命令
15 1
|
9天前
|
存储 运维 监控
构建高效稳定的Docker容器监控体系
【4月更文挑战第18天】 在现代微服务架构中,Docker容器已成为部署和运行应用的标准环境。随之而来的挑战是如何有效监控这些容器的性能与健康状况,确保系统的稳定性和可靠性。本文将探讨构建一个高效稳定的Docker容器监控体系的关键技术和方法,包括日志管理、性能指标收集以及异常检测机制,旨在为运维人员提供实用的指导和建议。
14 0
|
18天前
|
Linux Docker 容器
docker 容器常用命令
docker 容器常用命令
13 0

热门文章

最新文章