SpringBoot源码阅读:核心 —— 自动装配(2)

主要内容:

  1. 那些要被自动装配的类在哪儿
  2. AutoConfigurationImportSelector这个类是干嘛的

上一篇文章讲了@AutoConfigurationPackage如何获取主启动类的包名:SpringBoot源码阅读:核心 —— 自动装配(1)
@EnableAutoConfiguration还有一个@Import(AutoConfigurationImportSelector.class),这篇文章就从这里讲起
在这里插入图片描述
我们首先需要知道@Import的作用是导入第三方包加入到spring容器中,那我们来看看这个@AutoConfigurationImportSelector.class:

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

SpringBoot源码阅读:核心 —— 自动装配(2)_第1张图片
它是实现了ImportSelector的方法selectImports的

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		configurations = removeDuplicates(configurations);
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
		configurations.removeAll(exclusions);
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
		//打个断点
		return StringUtils.toStringArray(configurations);
	}

我们在最后的return语句打上断点看看运行结果:
SpringBoot源码阅读:核心 —— 自动装配(2)_第2张图片
它返回的是一个字符串数组,我们也可以看出来,这就是要被自动装配的类了!
好吧那我们来研究这些东西是怎么被灌到这个configurations数组中的?
selectImports里面有个getCandidateConfigurations,正是它返回了并且封装了configurations:

	/**
	  *返回应该考虑的自动配置类名。默认情况下
      *此方法将使用{@link SpringFactoriesLoader}加载候选对象
	  */
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		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;
	}

可见这些类都是通过SpringFactoriesLoader.loadFactoryNames来进行加载的:

	/**
	 * Load the fully qualified class names of factory implementations of the
	 * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
	 * class loader.
	 * @param factoryClass the interface or abstract class representing the factory
	 * @param classLoader the ClassLoader to use for loading resources; can be
	 * {@code null} to use the default
	 * @see #loadFactories
	 * @throws IllegalArgumentException if an error occurs while loading factory names
	 */
	public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
		String factoryClassName = factoryClass.getName();
		return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
	}

我们看看上面的注释就明白了,他大概说的是:
用给定的类加载器加载给定的类,这些给定的类就存在{@value #FACTORIES_RESOURCE_LOCATION}中,它是一个常量:

public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;

这是一个文件吧,它里面应该写了需要自动装配的类全限定名呢
这个文件在 spring-boot-autoconfiguration 包下可以找到。
spring-boot-autoconfiguration 包下 META-INF/spring.factories 节选:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
......

好的,又回到先前的selectImports,它返回的是一个String[],里面装的就是从META-INF/spring.factories解析出来的字符串数组,之后就会被装配到IOC容器中了

你可能感兴趣的:(SpringBoot)