Spring中refresh分析之finishBeanFactoryInitialization方法详解

简介: Spring中refresh分析之finishBeanFactoryInitialization方法详解

我们分析过registerListeners后,本文分析finishBeanFactoryInitialization方法。


该方法其将会拿到所有的beanDefinitionNames,遍历beanNames,其非抽象、是单例、未配置lazy_init属性或其值非true那么就会触发getBean的操作。最后会对其中是SmartInitializingSingleton 类型的触发其afterSingletonsInstantiated方法。


AbstractApplicationContext的finishBeanFactoryInitialization方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
  // Initialize conversion service for this context.
  // 尝试获取并设置conversionService-本文这里直接跳过
  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.
  // 尝试为beanFactory增加EmbeddedValueResolver,比如PropertyPlaceholderConfigurer 
  //本文这里也跳过
  if (!beanFactory.hasEmbeddedValueResolver()) {
    beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
  }
  // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
  // 获取并初始化LoadTimeWeaverAware-本文这里为空
  String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  for (String weaverAwareName : weaverAwareNames) {
    getBean(weaverAwareName);
  }
  // Stop using the temporary ClassLoader for type matching.
  // tempClassLoader置为null
  beanFactory.setTempClassLoader(null);
  // Allow for caching all bean definition metadata, not expecting further changes.
  //configurationFrozen=true
  //frozenBeanDefinitionNames=this.beanDefinitionNames
  //也就意味着这些bean定义被冷冻,不再支持修改
  beanFactory.freezeConfiguration();
  // Instantiate all remaining (non-lazy-init) singletons.
  //实例化所以非懒加载 单例 bean
  beanFactory.preInstantiateSingletons();
}

可以看到其对beanFactory做了一点配置后直接触发了preInstantiateSingletons方法。


DefaultListableBeanFactory的preInstantiateSingletons方法

@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.
  // 拿到beanDefinitionNames
  List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
  // Trigger initialization of all non-lazy singleton beans...
  for (String beanName : beanNames) {
    // 获取bean定义
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // 非抽象、单例、非懒加载
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    // 是否为工厂bean
      if (isFactoryBean(beanName)) {
      // FACTORY_BEAN_PREFIX = &
        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());
          }
          // 如果需要急切实例化,则触发getBean方法
          if (isEagerInit) {
            getBean(beanName);
          }
        }
      }
      else {
      // 非工厂bean直接触发实例化流程
        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到List<String> beanNames;

遍历beanNames,如果其是非抽象、单例、非懒加载:

如果其是FactoryBean则判断是否需要急切初始化,如果是则触发getBean流程;

如果不是FactoryBean,则直接触发getBean流程

遍历beanNames获取每个beanName对应的实例,如果其是SmartInitializingSingleton类型,则触发其afterSingletonsInstantiated方法。

SmartInitializingSingleton接口提供了afterSingletonsInstantiated方法,允许你在所有常规单例bean实例化之后触发。这里与InitializingBean的afterPropertiesSet有明显区别哦。


目录
相关文章
|
10天前
|
设计模式 Java Spring
spring源码设计模式分析(五)-策略模式
spring源码设计模式分析(五)-策略模式
|
8天前
|
负载均衡 Java 网络架构
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
21 5
|
10天前
|
消息中间件 设计模式 缓存
spring源码设计模式分析(四)-观察者模式
spring源码设计模式分析(四)-观察者模式
|
10天前
|
设计模式 Java Spring
spring源码设计模式分析(六)-模板方法模式
spring源码设计模式分析(六)-模板方法模式
|
9天前
|
Java 应用服务中间件 Spring
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
|
10天前
|
设计模式 Java Spring
spring源码设计模式分析(七)-委派模式
spring源码设计模式分析(七)-委派模式
|
10天前
|
设计模式 Java 数据库
spring源码设计模式分析(八)-访问者模式
spring源码设计模式分析(八)-访问者模式
|
10天前
|
设计模式 搜索推荐 Java
spring源码设计模式分析(三)
spring源码设计模式分析(三)
|
10天前
|
XML 存储 Java
Spring-源码深入分析(二)
Spring-源码深入分析(二)
|
10天前
|
XML 设计模式 Java
Spring-源码深入分析(一)
Spring-源码深入分析(一)
下一篇
无影云桌面