@SpringBootApplication
class App {
}
// @SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ImportAutoConfiguration
@ComponentScan(excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)})
@interface SpringBootApplication {
}
// 该注解就是一个普通的配置类标识
@Configuration
@interface SpringBootConfiguration {
}
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
@interface EnableAutoConfiguration {
}
// 该类和EnableAutoConfiguration效果差不多,ImportAutoConfigurationImportSelector也继承AutoConfigurationImportSelector
@Import(ImportAutoConfigurationImportSelector.class)
public @interface ImportAutoConfiguration {
}
/**
* 导入Registrar类,该类主要是导入BasePackages类,保存了需要扫描的包的信息
*
* @see {@link AutoConfigurationPackages.BasePackages}
* @see {@link AutoConfigurationPackages.Registrar#registerBeanDefinitions}
* 该类的作用就是将标@AutoConfigurationPackage注解的类的包名封装成BasePackages对象,然后注册为Bean
* <p/>
* 对于其他外部,如果需要获取到SpringBoot需要自动扫描的包,则可以获取BasePackages这个Bean
* @see {@link AutoConfigurationPackages#get}
* BeanName固定为AutoConfigurationPackages.class.getName
*/
@Import(AutoConfigurationPackages.Registrar.class)
@interface AutoConfigurationPackage {
}
// 自动配置标注了@AutoConfigurationPackage类作为需要扫描的包名
class AutoConfigurationPackages {
private static final String BEAN = AutoConfigurationPackages.class.getName();
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 注册BasePackages的Bean对象,保存了标注@AutoConfigurationPackage注解的类对应的包名
AutoConfigurationPackages.register(registry, new PackageImport(metadata).getPackageName());
}
// 确定导入包的信息
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
// 是否存在BasePackages的Bean对象
public static boolean has(BeanFactory beanFactory) {
return beanFactory.containsBean(BEAN) && !AutoConfigurationPackages.get(beanFactory).isEmpty();
}
// 获取需要扫描的包对应的Bean对象
public static List<String> get(BeanFactory beanFactory) {
try {
return beanFactory.getBean(BEAN, BasePackages.class).get();
} catch (NoSuchBeanDefinitionException ex) {
throw new IllegalStateException("Unable to retrieve @EnableAutoConfiguration base packages");
}
}
// 注册BasePackages的Bean对象,保存了标注@AutoConfigurationPackage注解的类对应的包名
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
// 如果容器中包含"AutoConfigurationPackages" => BasePackages这个Bean
if (registry.containsBeanDefinition(BEAN)) {
// 获取该Bean的BeanDefinition
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
// 添加构造参数
ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
// 将构造函数参数中的需要扫描的包名与给定的包名进行合并
String[] packages = AutoConfigurationPackages.addBasePackages(constructorArguments, packageNames);
// 重新添加进去
constructorArguments.addIndexedArgumentValue(0, packages);
return;
}
// 如果不存在BasePackagesBean,创建一个BasePackages的Bean对象
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(BasePackages.class);
// 添加构造参数
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册Bean
registry.registerBeanDefinition(BEAN, beanDefinition);
}
// 将构造函数参数中的需要扫描的包名与给定的包名进行合并
private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) {
String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue();
Set<String> merged = new LinkedHashSet<>();
merged.addAll(Arrays.asList(existing));
merged.addAll(Arrays.asList(packageNames));
return StringUtils.toStringArray(merged);
}
// 保存标注了@AutoConfigurationPackage类的包名
public static final class PackageImport {
// 保存标注了@AutoConfigurationPackage类的包名
private final String packageName;
// 注解的元信息
public PackageImport(AnnotationMetadata metadata) {
// 获取到标注注解的类对应的类名
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}
public String getPackageName() {
return this.packageName;
}
}
// 保存所有需要扫描的包名
// 该对象会作为Spring中的Bean对象
public static final class BasePackages {
// 需要扫描的包名,该字段是通过beanDefinition.getConstructorArgumentValues()通过构造参数传递的
private final List<String> packages;
public BasePackages(String... names) {
List<String> packages = new ArrayList<>();
// 遍历所有的包名
for (String name : names) {
// 保存这些需要扫描的包名
packages.add(name);
}
this.packages = packages;
}
List<String> get() {
return this.packages;
}
}
}
// 该类是一个延迟导入的类,通过@EnableAutoConfiguration注解导入的,该类会处理spring.factories中的配置类
class AutoConfigurationImportSelector implements DeferredImportSelector {
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 是否开启了自动导入功能,默认开启
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
// 获取所有符合条件的需要自动导入的配置类,以及需要排除的配置类封装成自动导入条目对象返回
AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
// 返回所有符合条件的配置类
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
/**
* 获取所有符合条件的需要自动导入的配置类,以及需要排除的配置类封装成自动导入条目对象返回
* <pre>
* 步骤:
* 1. 检查自动导入功能是否开启,如果开启了接下一步(key: spring.boot.enableautoconfiguration)
* 2. 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
* </pre>
*
* @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
* // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
* // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
* // AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
* // 并将properties封装成PropertiesAutoConfigurationMetadata对象
* 并将properties封装成PropertiesAutoConfigurationMetadata对象
* @param annotationMetadata 标注@EnableAutoConfiguration注解所在的类的元数据
* @return 所有自动导入的条目信息
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
// 是否开启了自动导入功能,默认开启
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 获取@EnableAutoConfiguration的属性信息
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 删除重复的配置,就是将List使用Set去重
configurations = this.removeDuplicates(configurations);
// 获取需要排除的类
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 校验排除的类是否是一个正确的类,是在spring.factories中存在的类,如果不存在,抛出异常
this.checkExcludedClasses(configurations, exclusions);
// 从所有的配置类中删除要排除的类
configurations.removeAll(exclusions);
// 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类对自己装配的类进行过滤
// 返回过滤后的配置类集合
configurations = this.filter(configurations, autoConfigurationMetadata);
// 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
// 并触发这些监听器的onAutoConfigurationImportEvent方法
this.fireAutoConfigurationImportEvents(configurations, exclusions);
// 将所有需要导入的配置类以及需要排除的配置类封装成自动导入条目对象返回
return new AutoConfigurationEntry(configurations, exclusions);
}
// 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
// 并触发这些监听器的onAutoConfigurationImportEvent方法
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
// 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
List<AutoConfigurationImportListener> listeners = this.getAutoConfigurationImportListeners();
// 如果存在监听器
if (!listeners.isEmpty()) {
// 发布一个自动导入配置的事件,将当前类,所有符合条件的配置类,以及需要排除的类封装
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
// 遍历所有的监听器
for (AutoConfigurationImportListener listener : listeners) {
// 执行这些Aware回调方法
this.invokeAwareMethods(listener);
// 回调监听器的onAutoConfigurationImportEvent方法
listener.onAutoConfigurationImportEvent(event);
}
}
}
// 执行对象的Aware接口方法
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);
}
}
}
// 从spring.factories文件中加载AutoConfigurationImportListener类型的实现类
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
}
// 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
// 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类对自己装配的类进行过滤
// 返回过滤后的配置类集合
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
// 从spring.factories文件中加载AutoConfigurationImportFilter类型的实现类
List<AutoConfigurationImportFilter> filters = this.getAutoConfigurationImportFilters();
// 遍历所有的过滤器
for (AutoConfigurationImportFilter filter : filters) {
// 执行filter的Aware方法
// BeanClassLoaderAware,BeanFactoryAware,EnvironmentAware,ResourceLoaderAware
this.invokeAwareMethods(filter);
// 调用filter的过滤方法,返回一个对应这所有候选配置类数组是否被排除的数组,一一对应
// 这里就是FilteringSpringBootCondition条件过滤器
// 处理ConditionalOnBean,ConditionalOnSingleCandidate,ConditionalOnClass,ConditionalOnMissingClass,ConditionalOnWebApplication这些注解
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
// 遍历这个对每一个类匹配的结果
for (int i = 0; i < match.length; i++) {
// 如果匹配失败
if (!match[i]) {
// 标识当前配置类需要被跳过
skip[i] = true;
// 将候选的类置空,因为这是一个循环,还有多个AutoConfigurationImportFilter要进行处理
candidates[i] = null;
// 标识存在需要跳过的类
skipped = true;
}
}
}
// 如果不存在被跳过的类,那么直接返回传递过来的配置类
if (!skipped) {
return configurations;
}
// 有需要被跳过的类
// 创建一个用于保存最终需要解析的配置类结果
List<String> result = new ArrayList<>(candidates.length);
// 遍历所有的配置类
for (int i = 0; i < candidates.length; i++) {
// 如果不需要被跳过
if (!skip[i]) {
// 保存配置
result.add(candidates[i]);
}
}
// 返回没有被跳过的类
return new ArrayList<>(result);
}
// 校验排除的类是否是一个正确的类,是在spring.factories中存在的类,如果不存在,抛出异常
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()) {
this.handleInvalidExcludes(invalidExcludes);
}
}
// 获取需要排除的类
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<>();
// 获取@EnableAutoConfiguration属性exclude的值
excluded.addAll(asList(attributes, "exclude"));
// 获取@EnableAutoConfiguration属性excludeName的值
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
// 获取环境配置中的spring.autoconfigure.exclude的属性值这个配置的值表示忽略哪些文件
excluded.addAll(this.getExcludeAutoConfigurationsProperty());
return excluded;
}
// 获取环境配置中的spring.autoconfigure.exclude的属性值这个配置的值表示忽略哪些文件
private List<String> getExcludeAutoConfigurationsProperty() {
if (getEnvironment() instanceof ConfigurableEnvironment) {
Binder binder = Binder.get(getEnvironment());
// 获取环境对象中spring.autoconfigure.exclude的属性,并绑定到字符串数组中返回
return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList).orElse(Collections.emptyList());
}
// 获取环境配置spring.autoconfigure.exclude的值
String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
}
// 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 从spring.factories中获取EnableAutoConfiguration的key对应所有类的名称
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, getBeanClassLoader());
return configurations;
}
// 是否开启了自动导入功能
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass() == AutoConfigurationImportSelector.class) {
// 获取配置属性为"spring.boot.enableautoconfiguration"的值,默认为true
return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
}
return true;
}
// 自动配置的元数据加载器
public class AutoConfigurationMetadataLoader {
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return AutoConfigurationMetadataLoader.loadMetadata(classLoader, PATH);
}
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path) : ClassLoader.getSystemResources(path);
// 保存META-INF/spring-autoconfigure-metadata.properties中的所有配置
Properties properties = new Properties();
// 遍历所有的文件
while (urls.hasMoreElements()) {
// 将该配置类中所有的键值对保存到properties中
properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
}
// 将所有属性配置封装为AutoConfigurationMetadata对象
return AutoConfigurationMetadataLoader.loadMetadata(properties) {
// 该对象就是从properties中获取对应的属性值
return new PropertiesAutoConfigurationMetadata(properties);
}
}
}
// 延迟导入处理类的分组
public static class AutoConfigurationGroup implements DeferredImportSelector.Group {
// 所有需要导入的配置类=>导入的来源类的映射关系
private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
// 所有需要自动导入的配置类条目信息,每一个AutoConfigurationEntry对象包含了这个模块对应所有需要导入的类
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
// 开始处理延迟导入的Bean操作
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
// 将AutoConfigurationImportSelector类解析好的AutoConfigurationEntry获取出来
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
// 保存到当前AutoConfigurationGroup类中
this.autoConfigurationEntries.add(autoConfigurationEntry);
// 遍历所有需要导入的配置类
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
// 保存所有需要保存的配置类
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
// 获取需要导入的所有类
// 将配置类转换为Entry类型,key为: 导入该配置类的来源类 ,值为: 该配置类名称
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 this.sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata())
.stream()
// 将配置类转换为Entry类型,key为: 导入该配置类的来源类 ,值为: 该配置类名称
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
// 返回的是PropertiesAutoConfigurationMetadata
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
if (this.autoConfigurationMetadata == null) {
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到autoConfigurationMetadata一个properties中
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
}
return this.autoConfigurationMetadata;
}
// 对说中配置类进行排序,最终得到所有配置类的加载顺序
private List<String> sortAutoConfigurations(Set<String> classNames, AutoConfigurationMetadata autoConfigurationMetadata) {
// 获取自动配置类的排序器
AutoConfigurationSorter sorter = new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata);
// 根据优先级排序,Order接口以及@AutoConfigureBefore @AutoConfigureAfter注解
// 最终得到所有配置类的加载顺序
List<String> result = sorter.getInPriorityOrder(classNames);
return result;
}
// 获取"org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"对应的元数据加载的工厂类的Bean
private MetadataReaderFactory getMetadataReaderFactory() {
// 获取"org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"对应的元数据加载的工厂类的Bean
return this.beanFactory.getBean(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME, MetadataReaderFactory.class);
}
}
// 自动配置类的排序器
class AutoConfigurationSorter {
// 类元数据的解析工厂
private final MetadataReaderFactory metadataReaderFactory;
// 自动配置类的属性配置元数据对象
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
private final AutoConfigurationMetadata autoConfigurationMetadata;
// 根据优先级排序,Order接口以及@AutoConfigureBefore @AutoConfigureAfter注解
// 最终得到所有配置类的加载顺序
public List<String> getInPriorityOrder(Collection<String> classNames) {
// 所有需要导入的类名,所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据对象包装成自动配置的类中AutoConfigurationClasses
AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory, this.autoConfigurationMetadata, classNames);
List<String> orderedClassNames = new ArrayList<>(classNames);
// 根据自然顺序进行排序
Collections.sort(orderedClassNames);
// 再根据Order接口进行排序
orderedClassNames.sort((o1, o2) -> {
int i1 = classes.get(o1).getOrder();
int i2 = classes.get(o2).getOrder();
return Integer.compare(i1, i2);
});
// 根据注解排序 @AutoConfigureBefore @AutoConfigureAfter
orderedClassNames = this.sortByAnnotation(classes, orderedClassNames);
return orderedClassNames;
}
// 根据注解排序 @AutoConfigureBefore @AutoConfigureAfter
private List<String> sortByAnnotation(AutoConfigurationClasses classes, List<String> classNames) {
// 所有需要排序的类
List<String> toSort = new ArrayList<>(classNames);
// 获取所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
toSort.addAll(classes.getAllNames());
// 已经拍好序类
Set<String> sorted = new LinkedHashSet<>();
// 已经处理过的类
Set<String> processing = new LinkedHashSet<>();
// 如果有需要排序的类
while (!toSort.isEmpty()) {
// 使用@AfterAnnotation进行排序
this.doSortByAfterAnnotation(classes, toSort, sorted, processing, null);
}
// 从已排好序的配置类中,删除在classNames中不存在的配置类
// 因为我们只需要classNames中的元素
sorted.retainAll(classNames);
// 返回排好序的结果
return new ArrayList<>(sorted);
}
//
/**
* 使用@AutoConfigureAfter注解进行排序,为什么没有按照@AutoConfigureBefore注解排序方法呢?
* 因为{@link AutoConfigurationClasses#getClassesRequestedAfter(String)}中,统一时候后置进行排序
* <pre>
* 什么意思呢?
* 如果我在你前面,那么,你就在我后面,因此,按照这种套路,就可以找到所有标记了我在他前面的类
* 这样,就能拿到我后面的所有类,这样,从第一个类开始,就可以按照先后顺序排到最后一个
* </pre>
*
* @param classes 需要排序的所有的类
* @param toSort 需要排序的类
* @param sorted 已经排好序的类
* @param processing 正在进行排序的类
* @param current 当前正在排序的类
*/
private void doSortByAfterAnnotation(AutoConfigurationClasses classes, List<String> toSort, Set<String> sorted, Set<String> processing, String current) {
// 如果当前排序的类为空,表示第一次使用这个类,取出第一个类开始排序
// 如果不为空,表示是通过递归处理的
if (current == null) {
current = toSort.remove(0);
}
// 保存正在处理的类
processing.add(current);
// 获取需要在当前类之后加载的类
Set<String> classesRequestedAfter = classes.getClassesRequestedAfter(current);
for (String after : classesRequestedAfter) {
// 如果未拍好序,并且该类需要排序
if (!sorted.contains(after) && toSort.contains(after)) {
// 递归排序,因为要一层一层排
// 例如: a要在b后面,a还要在c后面,b又要在c后面,这种顺序逻辑关系
// 最终得到 a在b后面,a也在c后面
this.doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
}
}
// 该类存储完毕,移除该类
processing.remove(current);
// 表示该类已经排好序了
sorted.add(current);
}
// 所有自动配置的类信息
public static class AutoConfigurationClasses {
// 保存所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
private final Map<String, AutoConfigurationClass> classes = new HashMap<>();
/**
* @param metadataReaderFactory 解析类元数据的工厂
* @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
* // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
* // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
* // AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
* // 并将properties封装成PropertiesAutoConfigurationMetadata对象
* @param classNames 所有需要处理的配置类
*/
public AutoConfigurationClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames) {
// 将所有符合装配条件的配置类通过META-INF/spring-autoconfigure-metadata.properties或者@AutoConfigureOrder,@AutoConfigureAfter,@AutoConfigureBefore注解描述的关系
// 将这些存在关系的类也进行保存,到时候也需要加载
this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, classNames, true);
}
/**
* 将所有符合装配条件的配置类通过META-INF/spring-autoconfigure-metadata.properties或者@AutoConfigureOrder,@AutoConfigureAfter,@AutoConfigureBefore注解描述的关系
* 将这些存在关系的类也进行保存,到时候也需要加载
*
* @param metadataReaderFactory 解析类元数据的工厂
* @param autoConfigurationMetadata // 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
* // 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一
* // 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
* // AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
* // 并将properties封装成PropertiesAutoConfigurationMetadata对象
* @param classNames 所有需要处理的配置类
* @param required 是否必须加载
*/
private void addToClasses(MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames, boolean required) {
// 遍历所有的类名
for (String className : classNames) {
// 如果该classes没有包含,表示没有处理过该类
if (!this.classes.containsKey(className)) {
// 创建单个自动配置类的信息,比如,要在那个类之后加载,之前加载等等
AutoConfigurationClass autoConfigurationClass = new AutoConfigurationClass(className, metadataReaderFactory, autoConfigurationMetadata);
// 该配置类是否可用
// 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
boolean available = autoConfigurationClass.isAvailable();
// 如果必须,或者可用,required: 从构造方法调用的,为true,递归调用的为false
if (required || available) {
// 保存需要自动装配的配置类
this.classes.put(className, autoConfigurationClass);
}
// 配置类可用
if (available) {
// 不断递归添加要在该类之前加载的类
this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getBefore(), false);
// 不断递归添加要在该类后加载的类
this.addToClasses(metadataReaderFactory, autoConfigurationMetadata, autoConfigurationClass.getAfter(), false);
}
}
}
}
// 获取所有需要自动装配的配置类,包含了与给定的配置类存在加载关系的类
public Set<String> getAllNames() {
return this.classes.keySet();
}
// 获取指定配置类的自动装配信息,比如,要在那个类之后加载,之前加载等等
public AutoConfigurationClass get(String className) {
return this.classes.get(className);
}
// 需要在该指定类之后加载的类
public Set<String> getClassesRequestedAfter(String className) {
// 获取需要在给定配置类之后加载的类名
Set<String> after = this.get(className).getAfter();
// 获取需要在该指定类之后加载的类
Set<String> classesRequestedAfter = new LinkedHashSet<>(after);
// 遍历所有需要加载的配置类信息
this.classes.forEach((String name, AutoConfigurationClass autoConfigurationClass) -> {
// 获取需要在正在遍历的配置类之前加载的类,如果这些类中包含当前指定的类
// 那么表示指定的类就需要在正在遍历的类后面加载
if (autoConfigurationClass.getBefore().contains(className)) {
// 保存需要在当前指定的类后面加载的类
// 说白了就是className需要在正在遍历的类之前加载,反过来,正在遍历的类需要在指定的当前类之后加载
classesRequestedAfter.add(name);
}
});
// 需要在该指定类之后加载的类
return classesRequestedAfter;
}
}
// 单个自动配置类的信息,比如,要在那个类之后加载,之前加载等等
public static class AutoConfigurationClass {
// 配置类类名
private final String className;
// 解析类的元数据工厂
private final MetadataReaderFactory metadataReaderFactory;
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,该配置文件是对自动配置的优化,这样就不需要获取类中的元数据注解再来决定类如何装配,实际上这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
private final AutoConfigurationMetadata autoConfigurationMetadata;
// 该配置类className对应的注解元信息
private volatile AnnotationMetadata annotationMetadata;
// 当前配置类在META-INF/spring-autoconfigure-metadata.properties配置的AutoConfigureBefore的类
// 也就是需要在当前类之前进行配置的类
private volatile Set<String> before;
// 当前配置类在META-INF/spring-autoconfigure-metadata.properties配置的AutoConfigureAfter的类
// 也就是需要在当前类之后进行配置的类
private volatile Set<String> after;
public AutoConfigurationClass(String className, MetadataReaderFactory metadataReaderFactory, AutoConfigurationMetadata autoConfigurationMetadata) {
this.className = className;
this.metadataReaderFactory = metadataReaderFactory;
this.autoConfigurationMetadata = autoConfigurationMetadata;
}
// 该配置类是否可用
// 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
public boolean isAvailable() {
try {
// 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
if (!this.wasProcessed()) {
// 获取该配置类对应的注解元信息,如果能获取到,表示该类存在,加载失败可能没引入这个类
this.getAnnotationMetadata();
}
// 这个类在META-INF/spring-autoconfigure-metadata.properties中存在,或者可以成功加载这个类
return true;
} catch (Exception ex) {
// 该类不存在
return false;
}
}
// 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureBefore对应的类
public Set<String> getBefore() {
if (this.before == null) {
// 所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据
this.before = (this.wasProcessed() ?
this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureBefore", Collections.emptySet())
// 如果META-INF/spring-autoconfigure-metadata.properties配置文件中不存在,就只能加载类中的注解来获取
// 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
: this.getAnnotationValue(AutoConfigureBefore.class));
}
return this.before;
}
// 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureAfter对应的类
public Set<String> getAfter() {
if (this.after == null) {
// 所有的META-INF/spring-autoconfigure-metadata.properties配置文件的数据
this.after = (this.wasProcessed() ? this.autoConfigurationMetadata.getSet(this.className, "AutoConfigureAfter", Collections.emptySet())
// 如果META-INF/spring-autoconfigure-metadata.properties配置文件中不存在,就只能加载类中的注解来获取
// 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
: this.getAnnotationValue(AutoConfigureAfter.class));
}
return this.after;
}
// 获取当前配置类在META-INF/spring-autoconfigure-metadata.properties配置文件中标识的AutoConfigureOrder对应的类
private int getOrder() {
// 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
if (this.wasProcessed()) {
// 默认Order为0
return this.autoConfigurationMetadata.getInteger(this.className, "AutoConfigureOrder", AutoConfigureOrder.DEFAULT_ORDER);
}
// 该类在META-INF/spring-autoconfigure-metadata.properties不存在配置,就只能加载类中的注解来获取
// 因为META-INF/spring-autoconfigure-metadata.properties中是对自动配置的优化,不用去解析类的元数据
Map<String, Object> attributes = this.getAnnotationMetadata().getAnnotationAttributes(AutoConfigureOrder.class.getName());
// 获取@AutoConfigureOrder注解对应的属性配置,默认值为:0
return (attributes != null) ? (Integer) attributes.get("value") : AutoConfigureOrder.DEFAULT_ORDER;
}
// 该类在META-INF/spring-autoconfigure-metadata.properties是否存在配置信息
private boolean wasProcessed() {
// 该类在META-INF/spring-autoconfigure-metadata.properties中配置了,autoConfigurationMetadata中的properties中存在该类的Key,就表示需要被加载
return (this.autoConfigurationMetadata != null && this.autoConfigurationMetadata.wasProcessed(this.className));
}
/**
* 获取指定注解的属性,包含@AutoConfigureAfter,@AutoConfigureBefore
*
* @param annotation 注解信息,@AutoConfigureAfter,@AutoConfigureBefore
* @return 该注解配置的value和name值
*/
private Set<String> getAnnotationValue(Class<?> annotation) {
// 获取该类的元数据中的指定注解信息
Map<String, Object> attributes = this.getAnnotationMetadata().getAnnotationAttributes(annotation.getName(), true);
// 如果不存在指定注解
if (attributes == null) {
return Collections.emptySet();
}
// 存在指定注解
Set<String> value = new LinkedHashSet<>();
// 保存该注解的value和name值
Collections.addAll(value, (String[]) attributes.get("value"));
Collections.addAll(value, (String[]) attributes.get("name"));
return value;
}
// 获取该配置类对应的注解元信息
private AnnotationMetadata getAnnotationMetadata() {
if (this.annotationMetadata == null) {
// 加载该配置类的元信息
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(this.className);
// 获取该配置类对应的注解元信息
this.annotationMetadata = metadataReader.getAnnotationMetadata();
}
return this.annotationMetadata;
}
}
// 加载所有的META-INF/spring-autoconfigure-metadata.properties配置文件,将全部保存到一个properties中
// 该配置文件存储着自动配置类的装配条件,这些与在类中配置的注解效果是一样的
// 例如: ConditionalOnSingleCandidate,ConditionalOnClass,AutoConfigureAfter
// AutoConfigureOrder,ConditionalOnBean,AutoConfigureBefore
// 并将properties封装成PropertiesAutoConfigurationMetadata对象
public static class PropertiesAutoConfigurationMetadata implements AutoConfigurationMetadata {
// 保存这所有META-INF/spring-autoconfigure-metadata.properties的配置信息
private final Properties properties;
public PropertiesAutoConfigurationMetadata(Properties properties) {
this.properties = properties;
}
// 该类在META-INF/spring-autoconfigure-metadata.properties配置文件是否存在
public boolean wasProcessed(String className) {
return this.properties.containsKey(className);
}
// 获取int类型的值
public Integer getInteger(String className, String key) {
return getInteger(className, key, null);
}
public Integer getInteger(String className, String key, Integer defaultValue) {
String value = get(className, key);
return (value != null) ? Integer.valueOf(value) : defaultValue;
}
// 获取set类型的值
public Set<String> getSet(String className, String key) {
return getSet(className, key, null);
}
public Set<String> getSet(String className, String key, Set<String> defaultValue) {
String value = get(className, key);
return (value != null) ? StringUtils.commaDelimitedListToSet(value) : defaultValue;
}
// 获取String类型的值
public String get(String className, String key) {
return get(className, key, null);
}
public String get(String className, String key, String defaultValue) {
String value = this.properties.getProperty(className + "." + key);
return (value != null) ? value : defaultValue;
}
}
}
}
/**
* 处理@ImportAutoConfiguration注解的类
*
* @see {@link AutoConfigurationImportSelector}
*/
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
// 可以解析的注解名
private static final Set<String> ANNOTATION_NAMES;
// 该类会处理@ImportAutoConfiguration和测试包的test.ImportAutoConfiguration注解
static {
Set<String> names = new LinkedHashSet<>();
// @ImportAutoConfiguration
names.add(ImportAutoConfiguration.class.getName());
// 测试包的@ImportAutoConfiguration注解
names.add("org.springframework.boot.autoconfigure.test.ImportAutoConfiguration");
ANNOTATION_NAMES = Collections.unmodifiableSet(names);
}
/**
* 确定需要导入的类
*
* @param metadata 标注@ImportAutoConfiguration类的元信息
*/
public Set<Object> determineImports(AnnotationMetadata metadata) {
// 获取候选的配置类,该类重写了默认的从spring.factories获取配置,而是从@ImportAutoConfiguration注解中获取需要导入的类
List<String> candidateConfigurations = this.getCandidateConfigurations(metadata, null);
Set<String> result = new LinkedHashSet<>(candidateConfigurations);
// 获取需要排除的类
Set<String> exclusions = this.getExclusions(metadata, null);
// 在获取的所有候选配置类中,删除要排除的类
result.removeAll(exclusions);
// 返回所有符合条件的配置类
return Collections.unmodifiableSet(result);
}
// 该类不处理
@Override
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
return null;
}
/**
* 获取候选的配置类,该类重写了默认的从spring.factories获取配置
*
* @param metadata 标注@ImportAutoConfiguration类的元信息
* @param attributes 注解属性信息,这个为空,因为当前类覆盖了父类的{@link ImportAutoConfigurationImportSelector#getAttributes}方法
* @return 所有符合条件的配置类
*/
@Override
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> candidates = new ArrayList<>();
// 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
// Key为出现@ImportAutoConfiguration的类的Class,Value为@ImportAutoConfiguration注解信息
// 用List作为Value是同时为了处理org.springframework.boot.autoconfigure.test.ImportAutoConfiguration注解
Map<Class<?>, List<Annotation>> annotations = this.getAnnotations(metadata);
// 遍历所有收集到了@ImportAutoConfiguration注解信息
annotations.forEach((source, sourceAnnotations) -> this.collectCandidateConfigurations(source, sourceAnnotations, candidates));
// 返回所有需要加载的配置类
return candidates;
}
/**
* 收集@ImportAutoConfiguration注解中需要导入的配置类信息
*
* @see {@link ImportAutoConfigurationImportSelector#getConfigurationsForAnnotation}
*/
private void collectCandidateConfigurations(Class<?> source, List<Annotation> annotations, List<String> candidates) {
// 遍历该配置类中存在的所有@ImportAutoConfiguration注解
// 用List作为Value是同时为了处理org.springframework.boot.autoconfigure.test.@ImportAutoConfiguration注解
// 因为这个配置类可以同时配置这两个注解
for (Annotation annotation : annotations) {
// 从@ImportAutoConfiguration注解信息中,获取需要导入的配置类
Collection<String> forAnnotation = this.getConfigurationsForAnnotation(source, annotation);
// 保存所有注解中导入的所有类的信息
candidates.addAll(forAnnotation);
}
}
/**
* 从@ImportAutoConfiguration注解信息中,获取需要导入的配置类
* <pre>
* 1. 如果@ImportAutoConfiguration标注了需要导入的类,那么导入的那个类才是配置类
* 2. 如果@ImportAutoConfiguration没有标注需要导入的类,只有一个注解
* 那么会加载标注该注解的类作为Key,从spring.factories获取对应的配置信息
* 例如:
* @ImportAutoConfiguration
* class A{}
* 那么,会自动从spring.factories中找a的全类名对应的配置类信息
* 2.1 再举个例子: 在自己项目中,创建一个org.springframework.boot.autoconfigure.EnableAutoConfiguration类
* 在类中标注@ImportAutoConfiguration注解,并将EnableAutoConfiguration类设置为SpringApplication的配置类
* 那么,与@EnableAutoConfiguration的作用几乎一样,但是一般不会这么做
* </pre>
*
* @param source 标注@ImportAutoConfiguration注解的为了或者注解
* @param annotation @ImportAutoConfiguration注解信息
* @return 所有配置类信息
*/
private Collection<String> getConfigurationsForAnnotation(Class<?> source, Annotation annotation) {
// 获取@ImportAutoConfiguration注解的信息
String[] classes = (String[]) AnnotationUtils.getAnnotationAttributes(annotation, true).get("classes");
// 如果配置了导入的配置类,那么直接返回这个配置类
if (classes.length > 0) {
return Arrays.asList(classes);
}
// 如果没有配置,那么会加载标注该注解的类作为Key,从spring.factories获取对应的配置信息
return loadFactoryNames(source);
}
// 根据指定类型名从spring.factories中获取该key对应的配置类信息
protected Collection<String> loadFactoryNames(Class<?> source) {
return SpringFactoriesLoader.loadFactoryNames(source, getClass().getClassLoader());
}
// 获取需要排除的类
@Override
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 所有需要的排除的类
Set<String> exclusions = new LinkedHashSet<>();
// 解析标注了@ImportAutoConfiguration注解的类(入口配置类)
Class<?> source = ClassUtils.resolveClassName(metadata.getClassName(), null);
// 遍历当前类所有的支持处理的注解
for (String annotationName : ANNOTATION_NAMES) {
// 获取到注解的属性信息
AnnotationAttributes merged = AnnotatedElementUtils.getMergedAnnotationAttributes(source, annotationName);
// 获取注解中需要排除的类
Class<?>[] exclude = (merged != null) ? merged.getClassArray("exclude") : null;
// 如果配置了
if (exclude != null) {
// 保存需要排除的类名
for (Class<?> excludeClass : exclude) {
exclusions.add(excludeClass.getName());
}
}
}
// 再解析入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
// 获取收集到的所有@ImportAutoConfiguration信息
List<Annotation>[] values = this.getAnnotations(metadata).values();
for (List<Annotation> annotations : values) {
// 遍历所有的@ImportAutoConfiguration注解
for (Annotation annotation : annotations) {
// 获取该注解的排除类属性
String[] exclude = (String[]) AnnotationUtils.getAnnotationAttributes(annotation, true).get("exclude");
// 如果不为空
if (!ObjectUtils.isEmpty(exclude)) {
// 保存需要排除的类
exclusions.addAll(Arrays.asList(exclude));
}
}
}
return exclusions;
}
// 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
protected final Map<Class<?>, List<Annotation>> getAnnotations(AnnotationMetadata metadata) {
MultiValueMap<Class<?>, Annotation> annotations = new LinkedMultiValueMap<>();
// 解析标注了@ImportAutoConfiguration类的类名
Class<?> source = ClassUtils.resolveClassName(metadata.getClassName(), null);
// 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
this.collectAnnotations(source, annotations, new HashSet<>());
return Collections.unmodifiableMap(annotations);
}
/**
* 收集入口配置类中所有的@ImportAutoConfiguration注解信息,包括注解中的,父类的
*
* @param source 需要收集@ImportAutoConfiguration注解的类的信息
* @param annotations 需要保存该source中的所有@ImportAutoConfiguration注解的类
* @param seen 已经处理过的类
*/
private void collectAnnotations(Class<?> source, MultiValueMap<Class<?>, Annotation> annotations, HashSet<Class<?>> seen) {
// 如果需要收集注解的类不为空,并且没有处理过
if (source != null && seen.add(source)) {
// 获取类中所有的注解
for (Annotation annotation : source.getDeclaredAnnotations()) {
// 如果不是java.lang.annotation包中的注解
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) {
// 如果存在@ImportAutoConfiguration注解
if (ANNOTATION_NAMES.contains(annotation.annotationType().getName())) {
// 保存该类与该@ImportAutoConfiguration注解的映射关系
annotations.add(source, annotation);
}
// 再根据当前注解类型再去找注解中的@ImportAutoConfiguration注解信息
this.collectAnnotations(annotation.annotationType(), annotations, seen);
}
}
// 找完了当前类,继续收集父类的@ImportAutoConfiguration注解信息
this.collectAnnotations(source.getSuperclass(), annotations, seen);
}
}
// 在AutoConfigurationImportSelector之前执行
@Override
public int getOrder() {
return super.getOrder() - 1;
}
// 处理用户排除的无效的类
@Override
protected void handleInvalidExcludes(List<String> invalidExcludes) {
}
}
spring项目add configuration
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
STS4 add spring bean configuration filespring .net
-
springboot3 支持容器
Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家。本文精选了三十五个常见的Spring Boot知识点,祝你一臂之力!问题一Spring Boot、Spring MVC 和 Spring 有什么区别?1、SpringSpring最重要的特征是依赖注入。所有 SpringModules 不是依赖注入就是 IOC 控制反转。当我们恰当的
springboot3 支持容器 springboot的嵌入式web容器 springboot部署到服务器 启动 spring 应用程序