栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

深入浅析SpringBoot中的自动装配

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入浅析SpringBoot中的自动装配

SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提。这次主要的议题是,来看看它是怎么样实现的,我们透过源代码来把握自动装配的来龙去脉。

一、自动装配过程分析

1.1、关于@SpringBootApplication

  我们在编写SpringBoot项目时,@SpringBootApplication是最常见的注解了,我们可以看一下源代码:


package org.springframework.boot.autoconfigure;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
 
 @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
 Class[] exclude() default {};
 
 @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
 String[] excludeName() default {};
 
 @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
 String[] scanbasePackages() default {};
 
 @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
 Class[] scanbasePackageClasses() default {};
}

  这里面包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan,此处@ComponentScan由于没有指定扫描包,因此它默认扫描的是与该类同级的类或者同级包下的所有类,另外@SpringBootConfiguration,通过源码得知它是一个@Configuration:


package org.springframework.boot;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Configuration
public @interface SpringBootConfiguration {
}

  由此我们可以推断出@SpringBootApplication等同于@Configuration @ComponentScan @EnableAutoConfiguration

1.2、@EnableAutoConfiguration

  一旦加上此注解,那么将会开启自动装配功能,简单点讲,Spring会试图在你的classpath下找到所有配置的Bean然后进行装配。当然装配Bean时,会根据若干个(Conditional)定制规则来进行初始化。我们看一下它的源码:


package org.springframework.boot.autoconfigure;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;
import org.springframework.core.io.support.SpringFactoriesLoader;

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import(EnableAutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {
 String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
 
 Class[] exclude() default {};
 
 String[] excludeName() default {};
}

  虽然根据文档注释的说明它指点我们去看EnableAutoConfigurationimportSelector。但是该类在SpringBoot1.5.X版本已经过时了,因此我们看一下它的父类AutoConfigurationimportSelector:


package org.springframework.boot.autoconfigure;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.linkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.DeferredimportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.Annotationmetadata;
import org.springframework.core.type.classreading.CachingmetadataReaderFactory;
import org.springframework.core.type.classreading.metadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

public class AutoConfigurationimportSelector
 implements DeferredimportSelector, BeanClassLoaderAware, ResourceLoaderAware,
 BeanFactoryAware, EnvironmentAware, Ordered {
 private static final String[] NO_importS = {};
 private static final Log logger = LogFactory
 .getLog(AutoConfigurationimportSelector.class);
 private ConfigurableListableBeanFactory beanFactory;
 private Environment environment;
 private ClassLoader beanClassLoader;
 private ResourceLoader resourceLoader;
 @Override
 public String[] selectimports(Annotationmetadata annotationmetadata) {
 if (!isEnabled(annotationmetadata)) {
 return NO_importS;
 }
 try {
 AutoConfigurationmetadata autoConfigurationmetadata = AutoConfigurationmetadataLoader
  .loadmetadata(this.beanClassLoader);
 AnnotationAttributes attributes = getAttributes(annotationmetadata);
 List configurations = getCandidateConfigurations(annotationmetadata,
  attributes);
 configurations = removeDuplicates(configurations);
 configurations = sort(configurations, autoConfigurationmetadata);
 Set exclusions = getExclusions(annotationmetadata, attributes);
 checkExcludedClasses(configurations, exclusions);
 configurations.removeAll(exclusions);
 configurations = filter(configurations, autoConfigurationmetadata);
 fireAutoConfigurationimportEvents(configurations, exclusions);
 return configurations.toArray(new String[configurations.size()]);
 }
 catch (IOException ex) {
 throw new IllegalStateException(ex);
 }
 }
 protected boolean isEnabled(Annotationmetadata metadata) {
 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;
 }
 
 protected Class getAnnotationClass() {
 return EnableAutoConfiguration.class;
 }
 
 protected List getCandidateConfigurations(Annotationmetadata metadata,
 AnnotationAttributes attributes) {
 List 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;
 }
 
 protected Class getSpringFactoriesLoaderFactoryClass() {
 return EnableAutoConfiguration.class;
 }
 private void checkExcludedClasses(List configurations,
 Set exclusions) {
 List 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);
 }
 }
 
 protected void handleInvalidExcludes(List 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));
 }
 
 protected Set getExclusions(Annotationmetadata metadata,
 AnnotationAttributes attributes) {
 Set excluded = new linkedHashSet();
 excluded.addAll(asList(attributes, "exclude"));
 excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
 excluded.addAll(getExcludeAutoConfigurationsProperty());
 return excluded;
 }
 private List getExcludeAutoConfigurationsProperty() {
 if (getEnvironment() instanceof ConfigurableEnvironment) {
 RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
  this.environment, "spring.autoconfigure.");
 Map properties = resolver.getSubProperties("exclude");
 if (properties.isEmpty()) {
 return Collections.emptyList();
 }
 List excludes = new ArrayList();
 for (Map.Entry entry : properties.entrySet()) {
 String name = entry.getKey();
 Object value = entry.getValue();
 if (name.isEmpty() || name.startsWith("[") && value != null) {
  excludes.addAll(new HashSet(Arrays.asList(StringUtils
  .tokenizeToStringArray(String.valueOf(value), ","))));
 }
 }
 return excludes;
 }
 RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
 "spring.autoconfigure.");
 String[] exclude = resolver.getProperty("exclude", String[].class);
 return (Arrays.asList(exclude == null ? new String[0] : exclude));
 }
 private List sort(List configurations,
 AutoConfigurationmetadata autoConfigurationmetadata) throws IOException {
 configurations = new AutoConfigurationSorter(getmetadataReaderFactory(),
 autoConfigurationmetadata).getInPriorityOrder(configurations);
 return configurations;
 }
 private List filter(List configurations,
 AutoConfigurationmetadata autoConfigurationmetadata) {
 long startTime = System.nanoTime();
 String[] candidates = configurations.toArray(new String[configurations.size()]);
 boolean[] skip = new boolean[candidates.length];
 boolean skipped = false;
 for (AutoConfigurationimportFilter filter : getAutoConfigurationimportFilters()) {
 invokeAwareMethods(filter);
 boolean[] match = filter.match(candidates, autoConfigurationmetadata);
 for (int i = 0; i < match.length; i++) {
 if (!match[i]) {
  skip[i] = true;
  skipped = true;
 }
 }
 }
 if (!skipped) {
 return configurations;
 }
 List result = new ArrayList(candidates.length);
 for (int i = 0; i < candidates.length; i++) {
 if (!skip[i]) {
 result.add(candidates[i]);
 }
 }
 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 new ArrayList(result);
 }
 protected List getAutoConfigurationimportFilters() {
 return SpringFactoriesLoader.loadFactories(AutoConfigurationimportFilter.class,
 this.beanClassLoader);
 }
 private metadataReaderFactory getmetadataReaderFactory() {
 try {
 return getBeanFactory().getBean(
  SharedmetadataReaderFactoryContextInitializer.BEAN_NAME,
  metadataReaderFactory.class);
 }
 catch (NoSuchBeanDefinitionException ex) {
 return new CachingmetadataReaderFactory(this.resourceLoader);
 }
 }
 protected final  List removeDuplicates(List list) {
 return new ArrayList(new linkedHashSet(list));
 }
 protected final List asList(AnnotationAttributes attributes, String name) {
 String[] value = attributes.getStringArray(name);
 return Arrays.asList(value == null ? new String[0] : value);
 }
 private void fireAutoConfigurationimportEvents(List configurations,
 Set exclusions) {
 List listeners = getAutoConfigurationimportListeners();
 if (!listeners.isEmpty()) {
 AutoConfigurationimportEvent event = new AutoConfigurationimportEvent(this,
  configurations, exclusions);
 for (AutoConfigurationimportListener listener : listeners) {
 invokeAwareMethods(listener);
 listener.onAutoConfigurationimportEvent(event);
 }
 }
 }
 protected List getAutoConfigurationimportListeners() {
 return SpringFactoriesLoader.loadFactories(AutoConfigurationimportListener.class,
 this.beanClassLoader);
 }
 private void invokeAwareMethods(Object instance) {
 if (instance instanceof Aware) {
 if (instance instanceof BeanClassLoaderAware) {
 ((BeanClassLoaderAware) instance)
  .setBeanClassLoader(this.beanClassLoader);
 }
 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);
 }
 }
 }
 @Override
 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
 Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
 this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
 }
 protected final ConfigurableListableBeanFactory getBeanFactory() {
 return this.beanFactory;
 }
 @Override
 public void setBeanClassLoader(ClassLoader classLoader) {
 this.beanClassLoader = classLoader;
 }
 protected ClassLoader getBeanClassLoader() {
 return this.beanClassLoader;
 }
 @Override
 public void setEnvironment(Environment environment) {
 this.environment = environment;
 }
 protected final Environment getEnvironment() {
 return this.environment;
 }
 @Override
 public void setResourceLoader(ResourceLoader resourceLoader) {
 this.resourceLoader = resourceLoader;
 }
 protected final ResourceLoader getResourceLoader() {
 return this.resourceLoader;
 }
 @Override
 public int getOrder() {
 return Ordered.LOWEST_PRECEDENCE - 1;
 }
}

  首先该类实现了DeferredimportSelector接口,这个接口继承了importSelector:


package org.springframework.context.annotation;
import org.springframework.core.type.Annotationmetadata;

public interface importSelector {
 
 String[] selectimports(Annotationmetadata importingClassmetadata);
}

  该接口主要是为了导入@Configuration的配置项,而DeferredimportSelector是延期导入,当所有的@Configuration都处理过后才会执行。

  回过头来我们看一下AutoConfigurationimportSelector的selectimport方法:

@Override
 public String[] selectimports(Annotationmetadata annotationmetadata) {
 if (!isEnabled(annotationmetadata)) {
 return NO_importS;
 }
 try {
 AutoConfigurationmetadata autoConfigurationmetadata = AutoConfigurationmetadataLoader
  .loadmetadata(this.beanClassLoader);
 AnnotationAttributes attributes = getAttributes(annotationmetadata);
 List configurations = getCandidateConfigurations(annotationmetadata,
  attributes);
 configurations = removeDuplicates(configurations);
 configurations = sort(configurations, autoConfigurationmetadata);
 Set exclusions = getExclusions(annotationmetadata, attributes);
 checkExcludedClasses(configurations, exclusions);
 configurations.removeAll(exclusions);
 configurations = filter(configurations, autoConfigurationmetadata);
 fireAutoConfigurationimportEvents(configurations, exclusions);
 return configurations.toArray(new String[configurations.size()]);
 }
 catch (IOException ex) {
 throw new IllegalStateException(ex);
 }
 }


  该方法刚开始会先判断是否进行自动装配,而后会从meta-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性,紧接着会调用getCandidateConfigurations方法:


 protected List getCandidateConfigurations(Annotationmetadata metadata,
 AnnotationAttributes attributes) {
 List 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;
 }
 
 protected Class getSpringFactoriesLoaderFactoryClass() {
 return EnableAutoConfiguration.class;
 }

  在这里又遇到我们的老熟人了--SpringFactoryiesLoader, 它会读取meta-INF/spring.factories下的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,进而得到需要装配的类。最后让所有配置在meta-INF/spring.factories下的AutoConfigurationimportListener执行AutoConfigurationimportEvent事件,代码如下:

private void fireAutoConfigurationimportEvents(List configurations,
 Set exclusions) {
 List listeners = getAutoConfigurationimportListeners();
 if (!listeners.isEmpty()) {
 AutoConfigurationimportEvent event = new AutoConfigurationimportEvent(this,
  configurations, exclusions);
 for (AutoConfigurationimportListener listener : listeners) {
 invokeAwareMethods(listener);
 listener.onAutoConfigurationimportEvent(event);
 }
 }
 }
 protected List getAutoConfigurationimportListeners() {
 return SpringFactoriesLoader.loadFactories(AutoConfigurationimportListener.class,
 this.beanClassLoader);
 }
二、何时进行自动装配

  在前面的环节里只是最终要确定哪些类需要被装配,在SpringBoot时何时处理这些自动装配的类呢?下面我们简要的分析一下:

2.1、AbstractApplicationContext的refresh方法:

  这个方法老生常谈了其中请大家关注一下这个方法:

// Invoke factory processors registered as beans in the context.
 invokeBeanFactoryPostProcessors(beanFactory);

  在这里是处理BeanFactoryPostProcessor的,那么我们在来看一下这个接口BeanDefinitionRegistryPostProcessor:


package org.springframework.beans.factory.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
 
 void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

  该接口继承了BeanFactoryPostProcessor。

2.2、ConfigurationClassPostProcessor 类

  该类主要处理@Configuration注解的,它实现了BeanDefinitionRegistryPostProcessor,  那么也间接实现了BeanFactoryPostProcessor,关键代码如下:

@Override
 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
 int factoryId = System.identityHashCode(beanFactory);
 if (this.factoriesPostProcessed.contains(factoryId)) {
  throw new IllegalStateException(
   "postProcessBeanFactory already called on this post-processor against " + beanFactory);
 }
 this.factoriesPostProcessed.add(factoryId);
 if (!this.registriesPostProcessed.contains(factoryId)) {
  // BeanDefinitionRegistryPostProcessor hook apparently not supported...
  // Simply call processConfigurationClasses lazily at this point then.
  processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
 }
 enhanceConfigurationClasses(beanFactory);
 beanFactory.addBeanPostProcessor(new importAwareBeanPostProcessor(beanFactory));
 }

 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
 //.....省略部分代码
 // Parse each @Configuration class
 ConfigurationClassParser parser = new ConfigurationClassParser(
  this.metadataReaderFactory, this.problemReporter, this.environment,
  this.resourceLoader, this.componentScanBeanNameGenerator, registry);
 Set candidates = new linkedHashSet(configCandidates);
 Set alreadyParsed = new HashSet(configCandidates.size());
 do {
  parser.parse(candidates);
  parser.validate();
  Set 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());
  }
  this.reader.loadBeanDefinitions(configClasses);
  alreadyParsed.addAll(configClasses);
  candidates.clear();
  if (registry.getBeanDefinitionCount() > candidateNames.length) {
  String[] newCandidateNames = registry.getBeanDefinitionNames();
  Set oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
  Set alreadyParsedClasses = new HashSet();
  for (ConfigurationClass configurationClass : alreadyParsed) {
   alreadyParsedClasses.add(configurationClass.getmetadata().getClassName());
  }
  for (String candidateName : newCandidateNames) {
   if (!oldCandidateNames.contains(candidateName)) {
   BeanDefinition bd = registry.getBeanDefinition(candidateName);
   if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    !alreadyParsedClasses.contains(bd.getBeanClassName())) {
    candidates.add(new BeanDefinitionHolder(bd, candidateName));
   }
   }
  }
  candidateNames = newCandidateNames;
  }
 }
 while (!candidates.isEmpty());
    // ....省略部分代码
 } 

其实这里注释已经很清楚了,我们可以清楚的看到解析每一个@ConfigurationClass的关键类是:ConfigurationClassParser,那么我们继续看一看这个类的parse方法:

public void parse(Set configCandidates) {
 this.deferredimportSelectors = new linkedList();
 for (BeanDefinitionHolder holder : configCandidates) {
  BeanDefinition bd = holder.getBeanDefinition();
  try {
  if (bd instanceof AnnotatedBeanDefinition) {
   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());
  }
  }
  catch (BeanDefinitionStoreException ex) {
  throw ex;
  }
  catch (Throwable ex) {
  throw new BeanDefinitionStoreException(
   "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
  }
 }
 processDeferredimportSelectors();
 }

  在这里大家留意一下最后一句processDeferredimportSelectors方法,在这里将会对DeferredimportSelector进行处理,这样我们就和AutoConfigurationSelectimporter结合到一起了:

private void processDeferredimportSelectors() {
 List deferredimports = this.deferredimportSelectors;
 this.deferredimportSelectors = null;
 Collections.sort(deferredimports, DEFERRED_import_COMPARATOR);
 for (DeferredimportSelectorHolder deferredimport : deferredimports) {
  ConfigurationClass configClass = deferredimport.getConfigurationClass();
  try {
  String[] imports = deferredimport.getimportSelector().selectimports(configClass.getmetadata());
  processimports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
  }
  catch (BeanDefinitionStoreException ex) {
  throw ex;
  }
  catch (Throwable ex) {
  throw new BeanDefinitionStoreException(
   "Failed to process import candidates for configuration class [" +
   configClass.getmetadata().getClassName() + "]", ex);
  }
 }
 }

请大家关注这句代码:String[] imports = deferredimport.getimportSelector().selectimports(configClass.getmetadata());在这里deferredimport的类型为DeferredimportSelectorHolder:

private static class DeferredimportSelectorHolder {
 private final ConfigurationClass configurationClass;
 private final DeferredimportSelector importSelector;
 public DeferredimportSelectorHolder(ConfigurationClass configClass, DeferredimportSelector selector) {
  this.configurationClass = configClass;
  this.importSelector = selector;
 }
 public ConfigurationClass getConfigurationClass() {
  return this.configurationClass;
 }
 public DeferredimportSelector getimportSelector() {
  return this.importSelector;
 }
 }

  在这个内部类里持有了一个DeferredimportSelector的引用,至此将会执行自动装配的所有操作

三、总结

  1)自动装配还是利用了SpringFactoriesLoader来加载meta-INF/spring.factoires文件里所有配置的EnableAutoConfgruation,它会经过exclude和filter等操作,最终确定要装配的类

  2)  处理@Configuration的核心还是ConfigurationClassPostProcessor,这个类实现了BeanFactoryPostProcessor, 因此当AbstractApplicationContext执行refresh方法里的invokeBeanFactoryPostProcessors(beanFactory)方法时会执行自动装配

以上所述是小编给大家介绍的SpringBoot中的自动装配,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/140954.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号