深入剖析Spring boot自动装配原理二(@Import)

前言

关于@Import注解的使用,在Spring源码中随处可见,其作用大家基本也都知道,无非就是注入指定的Bean到Spring IOC容器管理,只能作用用于类上,其用法分三种:普通的类直接注入、实现了ImportSelector接口的类、实现了ImportBeanDefinitionRegistrar接口的类,那么Spring具体是如何实现的?这三种方式又有何不同?一起跟进源码一探究竟,彻底了解Import的实现。

 

源码追踪(Spring版本:5.3.6-SNAPSHOT

众所周知Spring需要先初始化上下文容器,Spring上下文容器针对不同的场景设计了较多类型,不过都大同小异,这里拿其中的AnnotationConfigApplicationContext进行讲解,如果需要进一步了解Spring的每一个容器或者Spring的更多源码细节,可关注我,我会在后面的章节中逐步揭开Spring源码迷雾。

 

AnnotationConfigApplicationContext(AbstractApplicationContext)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   // 注解配置上下文初始化
   this();
   // 将配置组件(AppConfig)注册到AnnotationConfigApplicationContext上下文对象的beanFactory中(即将bean信息放入beanDefinitionMap中)
   register(componentClasses);
   // 刷新注册到AnnotationConfigApplicationContext上下文对象的相关属性
   refresh();
}

@Override
// AbstractApplicationContext公共方法
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
      // Prepare this context for refreshing.
      prepareRefresh();
      // 刷新AnnotationConfigApplicationContext上下文对象的BeanFactory并返回BeanFactory对象
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);
      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);
         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // 实例化并调用所有已注册的BeanFactoryPostProcessor的Bean到Spring容器中.
         invokeBeanFactoryPostProcessors(beanFactory);
    	......
         // 实例化所有BeanFactory中非延迟加载的Bean.
         finishBeanFactoryInitialization(beanFactory);
         // Last step: publish corresponding event.
         finishRefresh();
      }
     ......
}

 

PostProcessorRegistrationDelegate

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   ......
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the bean factory post-processors apply to them!
      // Separate between BeanDefinitionRegistryPostProcessors that implement
      // PriorityOrdered, Ordered, and the rest.
      List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
      // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
      // 获取BeanDefinitionRegistryPostProcessor类型的bean名称,注意这里获取到了名字为
      // org.springframework.context.annotation.internalConfigurationAnnotationProcessor的bean
      // (这个bean不是直接存在的,在AnnotationConfigUtils类中可查到其对应的Ben为ConfigurationClassPostProcessor)
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)获取到ConfigurationClassPostProcessor
            // 将ConfigurationClassPostProcessor添加到当前注册Bean的处理对象集合
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      // 将BeanDefinitionRegistryPostProcessor排序
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      // 将BeanDefinitionRegistryPostProcessor稍后注册到BeanFactory
      registryProcessors.addAll(currentRegistryProcessors);
      // 
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
      currentRegistryProcessors.clear();
      ......
}

通过调用PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors方法循环执行所有BeanDefinitionRegistryPostProcessor,将相关Bean注入BeanFacotry。这里通过调用ConfigurationClassPostProcessor 处理所有@Configuration配置类,其通过核心方法processConfigBeanDefinitions来处理相关Bean的注入。

ConfigurationClassPostProcessor

 

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 生成处理ID
   int factoryId = System.identityHashCode(beanFactory);
   // 判断后置处理器在registriesPostProcessed和factoriesPostProcessed中有没有被调用过
   if (this.factoriesPostProcessed.contains(factoryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
   }
   // 调用前保存factoryId,防止被重复调用
   this.factoriesPostProcessed.add(factoryId);
   if (!this.registriesPostProcessed.contains(factoryId)) {
      // 注入标有@configuration的Bean里面需要注入的类(如:@Import注解)
      processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
   }
   enhanceConfigurationClasses(beanFactory);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   // 需要处理的候选@configuration类
   List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
   // 获取BeanFactory中注入的所有beanDefinitionNames
   String[] candidateNames = registry.getBeanDefinitionNames();

   for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      // 检查当前Bean是否已当作配置类处理过
      if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
         if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
         }
      }
      // 检查当前Bean是否是配置类,如果是则添加到configCandidates中,后面进行处理
      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
         configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      }
   }
   // Return immediately if no @Configuration classes were found
   if (configCandidates.isEmpty()) {
      return;
   }
   ......
   // 准备解析 @Configuration 标注的类,构建解析对象
   ConfigurationClassParser parser = new ConfigurationClassParser(
         this.metadataReaderFactory, this.problemReporter, this.environment,
         this.resourceLoader, this.componentScanBeanNameGenerator, registry);
   // 配置Bean去重
   Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
   // 存储已解析过的配置类
   Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
   // 循环解析
   do {
      StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
      // 解析所有@Configuration标记Bean,并将解析的Bean信息存入ConfigurationClassParser的configurationClasses集合中
      parser.parse(candidates);
      parser.validate();
      Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
      configClasses.removeAll(alreadyParsed);

      // Read the model and create bean definitions based on its content
      if (this.reader == null) {
         this.reader = new ConfigurationClassBeanDefinitionReader(
               registry, this.sourceExtractor, this.resourceLoader, this.environment,
               this.importBeanNameGenerator, parser.getImportRegistry());
      }
      // 初始化所有配置类中的Bean(包含处理ImportBeanDefinitionRegistrars类),
      // 并将其放入Spring容器中(BeanFactory的beanDefinitionMap)
      this.reader.loadBeanDefinitions(configClasses);
      alreadyParsed.addAll(configClasses);
      processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
      candidates.clear();
      ......
   }
   while (!candidates.isEmpty());
   ......
}

通过调用ConfigurationClassParser#parse对@Configuration类进行解析。

ConfigurationClassParser

 

public void parse(Set<BeanDefinitionHolder> configCandidates) {
   for (BeanDefinitionHolder holder : configCandidates) {
      BeanDefinition bd = holder.getBeanDefinition();
      try {
         if (bd instanceof AnnotatedBeanDefinition) {
             // Configuration类为AnnotatedBean
            parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
         }
         else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
            parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
         }
         else {
            parse(bd.getBeanClassName(), holder.getBeanName());
         }
      }
      ......
   }
   this.deferredImportSelectorHandler.process();
}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
   processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
   // 判断是否需要跳过该配置类的解析(例如配置了@Conditional注解)
   if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
      return;
   }
   // 标识该配置类是否解析过
   ConfigurationClass existingClass = this.configurationClasses.get(configClass);
   ......

   // Recursively process the configuration class and its superclass hierarchy.
   // 将配置类转为SourceClass类
   SourceClass sourceClass = asSourceClass(configClass, filter);
   // 从当前配置类configClass开始向上沿着类继承结构逐层执行doProcessConfigurationClass,
	// 直到遇到的父类是由Java提供的类结束循环
   do {
      sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
   }
   while (sourceClass != null);
   this.configurationClasses.put(configClass, configClass);
}

@Nullable
protected final SourceClass doProcessConfigurationClass(
      ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
      throws IOException {
    // Component注解存在继承关系,递归处理嵌套类
   if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      // Recursively process any member (nested) classes first
      processMemberClasses(configClass, sourceClass, filter);
   }
   ......
   // 重点来了,在这里处理Import注解
   processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
   ......
   // Process superclass, if any
   if (sourceClass.getMetadata().hasSuperClass()) {
      String superclass = sourceClass.getMetadata().getSuperClassName();
      if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
         this.knownSuperclasses.put(superclass, configClass);
         // Superclass found, return its annotation metadata and recurse
         return sourceClass.getSuperClass();
      }
   }

   // No superclass -> processing is complete
   return null;
}

/**
  * 处理配置类上搜集到的@Import注解
  * @Param configuClass 配置类
  * @Param currentSourceClass 当前源码类
  * @Param importCandidates 所有的@Import注解的value
  * @Param exclusionFilter 需要排除的类
  * @Param checkForCircularImports 是否检查循环导入
  **/
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
      boolean checkForCircularImports) {

   if (importCandidates.isEmpty()) {
      return;
   }

   if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
   }
   else {
       // 开始处理配置类configClass上@Import所有的importCandidates
      this.importStack.push(configClass);
      try {
          // 循环处理每一个@Import,每个@Import可能导入三种类型的类 :
          // 1. ImportSelector
          // 2. ImportBeanDefinitionRegistrar
          // 3. 其他类型,都当作配置类处理,也就是相当于使用了注解@Configuration的配置类
         // 下面的for循环中对这三种情况执行了不同的处理逻辑
         for (SourceClass candidate : importCandidates) {
            // 处理ImportSelector类(Spring Boot的自动装配采用的是这种方式)
            if (candidate.isAssignable(ImportSelector.class)) {
               // 加载对应的ImportSelector实现类
               Class<?> candidateClass = candidate.loadClass();
               // 实例化对应的实现ImportSelector的类
               ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                     this.environment, this.resourceLoader, this.registry);
               // 获取ImportSelector类中需要排除的实例化的类
               Predicate<String> selectorFilter = selector.getExclusionFilter();
               if (selectorFilter != null) {
                  exclusionFilter = exclusionFilter.or(selectorFilter);
               }
               // 后置处理类交由后置处理器进行处理,本类涵盖代码的第18行代码处理(this.deferredImportSelectorHandler.process();)
               if (selector instanceof DeferredImportSelector) {
                  this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
               }
               else {
                   // 调用实现ImportSelector的类的selectImports,获取需要实例化类的className
                  String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                  // 从当前ImportSelector需要实例化的类开始向上沿着类继承结构逐层执行将className加入到BeanFactory的beanDefinitionMap中(要排除的类除外),
        	        // 直到遇到的父类是由Java提供的类结束循环
                  Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                  // 循环处理importClassNames类中再包含的import类
                  processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
               }
            }
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
               // Candidate class is an ImportBeanDefinitionRegistrar ->
               // delegate to it to register additional bean definitions
               Class<?> candidateClass = candidate.loadClass();
               // 直接实例化ImportBeanDefinitionRegistrar 类
               ImportBeanDefinitionRegistrar registrar =
                     ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                           this.environment, this.resourceLoader, this.registry);
               // 将ImportBeanDefinitionRegistrar 类加入到importBeanDefinitionRegistrars集合中
               // 会在ConfigurationClassPostProcessor第69行代码进行处理
               configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
               // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
               // process it as an @Configuration class
               this.importStack.registerImport(
                     currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
               // 非ImportSelector or ImportBeanDefinitionRegistrar直接处理,放入BeanFactory中
               processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
            }
         }
      }
      ......
   }
}

通过以上的步骤已将Import中的类注入到BeanFacotry的beanDefinitionMap中等待实例化(ImportBeanDefinitionRegistrar类型的Bean需要通过下面的方式处理才能放入),回到ConfigurationClassPostProcessor的69行代码(this.reader.loadBeanDefinitions(configClasses);),调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions进行处理。

ConfigurationClassBeanDefinitionReader

 

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
   for (ConfigurationClass configClass : configurationModel) {
      loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
   }
}

private void loadBeanDefinitionsForConfigurationClass(
      ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
   ......
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
   // 获取所有ImportBeanDefinitionRegistrars进行处理
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) ->
         // 调用继承ImportBeanDefinitionRegistrar类中的registerBeanDefinitions将Bean注入到BeanFactory
         registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}

到这一步Import的所有类已注册到BeanFactory中,那么什么时候对这些类进行初始化呢?回到AnnotationConfigApplicationContext(即AbstractApplicationContext)的refresh方法,通过finishBeanFactoryInitialization(beanFactory)实例化Bean。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值