主要内容:
上一篇文章讲了@AutoConfigurationPackage如何获取主启动类的包名:SpringBoot源码阅读:核心 —— 自动装配(1)
@EnableAutoConfiguration还有一个@Import(AutoConfigurationImportSelector.class),这篇文章就从这里讲起
我们首先需要知道@Import的作用是导入第三方包加入到spring容器中,那我们来看看这个@AutoConfigurationImportSelector.class:
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered
它是实现了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语句打上断点看看运行结果:
它返回的是一个字符串数组,我们也可以看出来,这就是要被自动装配的类了!
好吧那我们来研究这些东西是怎么被灌到这个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容器中了