深入剖析Spring boot自动装配原理三(@EnableAutoConfiguration)

概要

何为自动装配?自动装配可简单理解为Spring自动读取配置类信息,并解析配置类中的Bean信息,然后将相关Bean初始化到IOC容器中。前面两个章节已经了解了SPI技术和Spring中Import注解的实现原理,本章节来具体讲解Spring boot如何使用通过EnableAutoConfiguration注解将Bean自动注入到Spring容器中。

源码剖析

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Spring Boot将相关配置都集成到了SpringBootApplication注解,在启动类加上该注解则标识为Spring Boot应用,进入SpringBootApplication类可以看到该类集成了@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解,SpringBootConfiguration继承了@Configuration,标识该类为Spring的配置类,在Spring启动IOC容器的时候可以识别并解析,ComponentScan表示IOC容器启动时,需要去扫描注册的Spring组件,EnableAutoConfiguration即标识开启Spring Boot 自动配置,进入之后发现其主要包含了两个注解,一个为AutoConfigurationPackage,另一个为Import,AutoConfigurationPackage默认没有扫描的包路径暂忽略,Import注解导入了AutoConfigurationImportSelector,该类为Spring Boot自动装配核心类,通过该类自动装载了Spring Boot需要的对象到IOC,下面对该类进行重点讲解。

首先上源码

AutoConfigurationImportSelector

.public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
      ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

   private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();

   private static final String[] NO_IMPORTS = {};

   private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);

   private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";

   private ConfigurableListableBeanFactory beanFactory;

   private Environment environment;

   // 类加载器(AppClassLoader)
   private ClassLoader beanClassLoader;

   private ResourceLoader resourceLoader;

   private ConfigurationClassFilter configurationClassFilter;

   @Override
   // 获取需要自动装载的Bean的classname集合
   // ConfigurationClassPostProcessor解析配置类的时候会调用该方法
   public String[] selectImports(AnnotationMetadata annotationMetadata) {
      // 是否需要导入类,默认需要,不会进入此判断
      if (!isEnabled(annotationMetadata)) {
         return NO_IMPORTS;
      }
      // 获取自动装配对象(里面包含需要解析的配置类)
      AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
      // 返回自动装配Bean的classname集合
      return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
   }

   @Override
   public Predicate<String> getExclusionFilter() {
      return this::shouldExclude;
   }

   private boolean shouldExclude(String configurationClassName) {
      return getConfigurationClassFilter().filter(Collections.singletonList(configurationClassName)).isEmpty();
   }

   /**
    * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
    * of the importing {@link Configuration @Configuration} class.
    * @param annotationMetadata the annotation metadata of the configuration class
    * @return the auto-configurations that should be imported
    */
   protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
      if (!isEnabled(annotationMetadata)) {
         return EMPTY_ENTRY;
      }
      // 获取配置类所有注解属性,此处传入的类为EnableAutoConfiguration,获取到exclude和excludeName属性
      AnnotationAttributes attributes = getAttributes(annotationMetadata);
      // 获取配置类标注的所有候选配置类信息
      List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
      // 去除重复项
      configurations = removeDuplicates(configurations);
      // 获取需要排除的配置类(不需要注入容器的Bean)
      Set<String> exclusions = getExclusions(annotationMetadata, attributes);
      // 检查排除的配置类的合法性,如果不合法则抛出异常
      checkExcludedClasses(configurations, exclusions);
      // 从需要解析的配置类集合中剔除需要排除的配置类
      configurations.removeAll(exclusions);
      // 获取配置类过滤器对配置类进行过滤
      configurations = getConfigurationClassFilter().filter(configurations);
      // 开启记录自动化配置过程中条件匹配的详细信息及日志信息
      fireAutoConfigurationImportEvents(configurations, exclusions);
      return new AutoConfigurationEntry(configurations, exclusions);
   }

   @Override
   public Class<? extends Group> getImportGroup() {
      return AutoConfigurationGroup.class;
   }

   protected boolean isEnabled(AnnotationMetadata metadata) {
      if (getClass() == AutoConfigurationImportSelector.class) {
         return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
      }
      return true;
   }

    // 获取注解的所有属性
   protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
      String name = getAnnotationClass().getName();
      AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
      Assert.notNull(attributes, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
            + " annotated with " + ClassUtils.getShortName(name) + "?");
      return attributes;
   }

   /**
    * Return the source annotation class used by the selector.
    * @return the annotation class
    */
   protected Class<?> getAnnotationClass() {
      return EnableAutoConfiguration.class;
   }

   /**
    * Return the auto-configuration class names that should be considered. By default
    * this method will load candidates using {@link SpringFactoriesLoader} with
    * {@link #getSpringFactoriesLoaderFactoryClass()}.
    * @param metadata the source metadata
    * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
    * attributes}
    * @return a list of candidate configurations
    */
   protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
      /**
       * 通过SpringFactoriesLoader去所有jar包中META-INF/spring.factories路径下获取
       * 标注key为org.springframework.boot.autoconfigure.EnableAutoConfiguration(getSpringFactoriesLoaderFactoryClass返回值)的所有配置类。
       * org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
       * org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
       * org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
       * org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
       * SpringFactoriesLoader.loadFactoryNames运用SPI的机制读取文件内容(不清楚SPI可以参考第一章节)
       **/
      List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
            getBeanClassLoader());
      Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
            + "are using a custom packaging, make sure that file is correct.");
      return configurations;
   }

   /**
    * Return the class used by {@link SpringFactoriesLoader} to load configuration
    * candidates.
    * @return the factory class
    */
   protected Class<?> getSpringFactoriesLoaderFactoryClass() {
      return EnableAutoConfiguration.class;
   }

   private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
      // 如果排除的配置类能能正常加载,并且在自动装配的配置类集合中不存在,则添加到非验证的排除类集合中
      List<String> invalidExcludes = new ArrayList<>(exclusions.size());
      for (String exclusion : exclusions) {
         // 检验类能否加载
         if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
            invalidExcludes.add(exclusion);
         }
      }
      // 非验证的排除类集合不为空的话抛出异常
      if (!invalidExcludes.isEmpty()) {
         handleInvalidExcludes(invalidExcludes);
      }
   }

   /**
    * Handle any invalid excludes that have been specified.
    * @param invalidExcludes the list of invalid excludes (will always have at least one
    * element)
    */
   protected void handleInvalidExcludes(List<String> invalidExcludes) {
      StringBuilder message = new StringBuilder();
      for (String exclude : invalidExcludes) {
         message.append("\t- ").append(exclude).append(String.format("%n"));
      }
      throw new IllegalStateException(String.format(
            "The following classes could not be excluded because they are not auto-configuration classes:%n%s",
            message));
   }

   /**
    * Return any exclusions that limit the candidate configurations.
    * @param metadata the source metadata
    * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
    * attributes}
    * @return exclusions or an empty set
    */
   protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
      Set<String> excluded = new LinkedHashSet<>();
      excluded.addAll(asList(attributes, "exclude"));
      excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
      excluded.addAll(getExcludeAutoConfigurationsProperty());
      return excluded;
   }

   /**
    * Returns the auto-configurations excluded by the
    * {@code spring.autoconfigure.exclude} property.
    * @return excluded auto-configurations
    * @since 2.3.2
    */
   protected List<String> getExcludeAutoConfigurationsProperty() {
      Environment environment = getEnvironment();
      if (environment == null) {
         return Collections.emptyList();
      }
      if (environment instanceof ConfigurableEnvironment) {
         Binder binder = Binder.get(environment);
         return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)
               .orElse(Collections.emptyList());
      }
      String[] excludes = environment.getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
      return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
   }

   protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
      return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
   }

   private ConfigurationClassFilter getConfigurationClassFilter() {
      if (this.configurationClassFilter == null) {
         /**
          * 获取配置类过滤器
          * 通过SpringFactoriesLoader去所有jar包中(此处为spring-boot-autoconfigure jar包)META-INF/spring.factories中
          * 标注key为oorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter的所有过滤器
          * org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
          * org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
          * org.springframework.boot.autoconfigure.condition.OnClassCondition,\
          * org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
          * 这些类作用于Conditional开头的注解,例如ConditionalOnBean、ConditionalOnMissingBean、ConditionalOnMissingClass等
          */
         List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
         for (AutoConfigurationImportFilter filter : filters) {
            // 调用Aware接口方法,将相关属性设置到Aware实现类的属性中,
            //此处是将容器的工厂设置到过滤器的beanFactory属性中
            invokeAwareMethods(filter);
         }
         this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
      }
      return this.configurationClassFilter;
   }

    // 通过set去重
   protected final <T> List<T> removeDuplicates(List<T> list) {
      return new ArrayList<>(new LinkedHashSet<>(list));
   }

   protected final List<String> asList(AnnotationAttributes attributes, String name) {
      String[] value = attributes.getStringArray(name);
      return Arrays.asList(value);
   }

   private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
      /**
       * 通过SpringFactoriesLoader去所有jar包中(此处为spring-boot-autoconfigure jar包)META-INF/spring.factories中
       * 标注key为oorg.springframework.boot.autoconfigure.AutoConfigurationImportListener的所有监听器
       * org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
       * org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
       */
      List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
      if (!listeners.isEmpty()) {
         AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
         for (AutoConfigurationImportListener listener : listeners) {
            // 调用Aware接口方法,将相关属性设置到Aware实现类的属性中,
            //此处是将容器的工厂设置到过滤器的beanFactory属性中
            invokeAwareMethods(listener);
            listener.onAutoConfigurationImportEvent(event);
         }
      }
   }

   protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
      return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
   }

   private void invokeAwareMethods(Object instance) {
      if (instance instanceof Aware) {
         // 设置Bean的类装载器
         if (instance instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) instance).setBeanClassLoader(this.beanClassLoader);
         }
         // 设置Bean工厂
         if (instance instanceof BeanFactoryAware) {
            ((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
         }
         //
         if (instance instanceof EnvironmentAware) {
            ((EnvironmentAware) instance).setEnvironment(this.environment);
         }
         // 设置资源加载器
         if (instance instanceof ResourceLoaderAware) {
            ((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
         }
      }
   }

   ......

   private static class ConfigurationClassFilter {

      private final AutoConfigurationMetadata autoConfigurationMetadata;

      private final List<AutoConfigurationImportFilter> filters;

      ConfigurationClassFilter(ClassLoader classLoader, List<AutoConfigurationImportFilter> filters) {
         this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(classLoader);
         this.filters = filters;
      }

      // 将不符合的配置类剔除,例如配置了ConditionalOnMissingClass,则表示ConditionalOnMissingClass注解中配置的类不存在才会加载当前类
      List<String> filter(List<String> configurations) {
         long startTime = System.nanoTime();
         String[] candidates = StringUtils.toStringArray(configurations);
         boolean skipped = false;
         for (AutoConfigurationImportFilter filter : this.filters) {
            /**
             * 对需要加载的配置类进行过滤处理,
             * 处理配置了Conditional开头的注解的配置类,
             * 具体过滤规则可阅读FilteringSpringBootCondition的match方法
             */
            boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
            for (int i = 0; i < match.length; i++) {
               // 如果过滤规则匹配成功,则将配置类删除(数组元素赋空)
               if (!match[i]) {
                  candidates[i] = null;
                  skipped = true;
               }
            }
         }
         // 匹配不到返回原配置类集合
         if (!skipped) {
            return configurations;
         }
         // 将空的配置类删除,并返回删除之后的配置类集合
         List<String> result = new ArrayList<>(candidates.length);
         for (String candidate : candidates) {
            if (candidate != null) {
               result.add(candidate);
            }
         }
         if (logger.isTraceEnabled()) {
            int numberFiltered = configurations.size() - result.size();
            logger.trace("Filtered " + numberFiltered + " auto configuration class in "
                  + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
         }
         return result;
      }

   }

   private static class AutoConfigurationGroup
         implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {

      private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();

      private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();

      ......

      @Override
      public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
         Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
               () -> String.format("Only %s implementations are supported, got %s",
                     AutoConfigurationImportSelector.class.getSimpleName(),
                     deferredImportSelector.getClass().getName()));
         // 获取自动装配对象(里面包含需要解析的配置类)
         AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
               .getAutoConfigurationEntry(annotationMetadata);
         this.autoConfigurationEntries.add(autoConfigurationEntry);
         for (String importClassName : autoConfigurationEntry.getConfigurations()) {
            this.entries.putIfAbsent(importClassName, annotationMetadata);
         }
      }

      @Override
      public Iterable<Entry> selectImports() {
         if (this.autoConfigurationEntries.isEmpty()) {
            return Collections.emptyList();
         }
         // 获取需要排除的类
         Set<String> allExclusions = this.autoConfigurationEntries.stream()
               .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
         // 获取所有需要解析的配置类
         Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
               .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
               .collect(Collectors.toCollection(LinkedHashSet::new));
         // 移除不需要处理的配置类
         processedConfigurations.removeAll(allExclusions);

         return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
               .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
               .collect(Collectors.toList());
      }

      private AutoConfigurationMetadata getAutoConfigurationMetadata() {
         if (this.autoConfigurationMetadata == null) {
            this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
         }
         return this.autoConfigurationMetadata;
      }

      private List<String> sortAutoConfigurations(Set<String> configurations,
            AutoConfigurationMetadata autoConfigurationMetadata) {
         return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
               .getInPriorityOrder(configurations);
      }

      private MetadataReaderFactory getMetadataReaderFactory() {
         try {
            return this.beanFactory.getBean(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
                  MetadataReaderFactory.class);
         }
         catch (NoSuchBeanDefinitionException ex) {
            return new CachingMetadataReaderFactory(this.resourceLoader);
         }
      }

   }

   protected static class AutoConfigurationEntry {

      private final List<String> configurations;

      private final Set<String> exclusions;

      private AutoConfigurationEntry() {
         this.configurations = Collections.emptyList();
         this.exclusions = Collections.emptySet();
      }

      /**
       * Create an entry with the configurations that were contributed and their
       * exclusions.
       * @param configurations the configurations that should be imported
       * @param exclusions the exclusions that were applied to the original list
       */
      AutoConfigurationEntry(Collection<String> configurations, Collection<String> exclusions) {
         this.configurations = new ArrayList<>(configurations);
         this.exclusions = new HashSet<>(exclusions);
      }

      public List<String> getConfigurations() {
         return this.configurations;
      }

      public Set<String> getExclusions() {
         return this.exclusions;
      }

   }

}

由于AutoConfigurationImportSelector实现了DeferredImportSelector(延迟导入)接口,其自动装配会经过ConfigurationClassParser进行后置处理(this.deferredImportSelectorHandler.process(),通过ConfigurationClassParserKaTeX parse error: Expected 'EOF', got '#' at position 30: …SelectorHandler#̲process方法处理)。 D…Group(即不能的选择器分配到不同的组),然后调用分组内部方法process(DeferredImportSelectorKaTeX parse error: Expected 'EOF', got '#' at position 6: Group#̲process)解析META-…Group#selectImports)返回需要进行自动装配的配置类实体集合,之后交给ConfigurationClassParser#processImports进行解析。

private class DeferredImportSelectorHandler {

   @Nullable
   private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
   ......
   // 延迟导入选择器后置解析入口
   public void process() {
      List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
      this.deferredImportSelectors = null;
      try {
         if (deferredImports != null) {
            DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
            // 排序
            deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
            // 循环调用DeferredImportSelectorGroupingHandler#register方法,将选择器分组信息注入
            deferredImports.forEach(handler::register);
            // 调用DeferredImportSelectorGroupingHandler#processGroupImports方法处理组内需要导入的配置类
            handler.processGroupImports();
         }
      }
      finally {
         this.deferredImportSelectors = new ArrayList<>();
      }
   }
}

private class DeferredImportSelectorGroupingHandler {

   private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();

   private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();

   public void register(DeferredImportSelectorHolder deferredImport) {
       // 调用DeferredImportSelector#getImportGroup方法获取分组信息
       // AutoConfigurationImportSelector#getImportGroup
      Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
      // 如果groupings集合中存在当前分组则直接返回分组信息,否则存入结合再返回
      DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
            (group != null ? group : deferredImport),
            key -> new DeferredImportSelectorGrouping(createGroup(group)));
      // 延迟导入选择器分组对象存入当前延迟导入选择器处理Bean,等待回调选择器的process方法的时候传入
      // AutoConfigurationImportSelector$AutoConfigurationGroup#process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector)
      // 此处的deferredImportSelector为AutoConfigurationImportSelector
      grouping.add(deferredImport);
      this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
            deferredImport.getConfigurationClass());
   }

   public void processGroupImports() {
      for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
         Predicate<String> exclusionFilter = grouping.getCandidateFilter();
         grouping.getImports().forEach(entry -> {
            ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
            try {
                // 递归解析需要注入的配置类
               processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
                     Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
                     exclusionFilter, false);
            }
            ......
         });
      }
   }
    ......
}

private static class DeferredImportSelectorGrouping {
   ......
   public Iterable<Group.Entry> getImports() {
      for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
          // 调用后置导入选择器分组process方法(AutoConfigurationImportSelector$AutoConfigurationGroup#process,获取需要装载的配置类集合)
         this.group.process(deferredImport.getConfigurationClass().getMetadata(),
               deferredImport.getImportSelector());
      }
      // 调用后置导入选择器分组selectImports方法返回需要装载的配置类实体集合
      return this.group.selectImports();
   }
    ......
}

ImportSelector是直接调用ImportSelector#selectImports方法,获取需要自动装配的配置类classname集合,之后交给ConfigurationClassParser#processImports进行解析。

总结:

Spring Boot自动装配的流程是先通过SpringApplication将@SpringApplication注解类注入到Spring IOC容器,然后通过ConfigurationClassParser对标注@Configuration的类进行解析,当解析到@EnableAutoConfiguration注解的时候,发现其内部通过Import注解导入了AutoConfigurationImportSelector类,ConfigurationClassParser通过processImports方法去解析AutoConfigurationImportSelector。AutoConfigurationImportSelector通过selectImports方法运用SPI机制获取Spring Boot所有jar包内META-INF/spring.factories文件内路径标注key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置类,然后通过一些列的excludeFilter排除相关配置类,获取到相关配置类之后,交由ConfigurationClassParser解析出来,并存入Spring IOC容器对应BeanFactory的beanDefinitionMap中,最终通过DefaultListableBeanFactory#preInstantiateSingletons进行实例化,该过程就将Spring Boot的一些Bean自动注入到了Spring IOC容器中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值