引入EnableAutoConfiguration注解
@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 {
}
由@Import引入AutoConfigurationImportSelector组件
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
处理需要装配组件的数据
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
// 获取所需要装配组件的数据
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
// 扫描并加载所有jar 下的META-INF/spring-autoconfigure-metadata.properties
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
if (this.autoConfigurationMetadata == null) {
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
}
return this.autoConfigurationMetadata;
}
扫描并加载所有jar 下的META-INF/spring-autoconfigure-metadata.properties
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
try {
// 获取META-INF/spring-autoconfigure-metadata.properties的资源
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
: ClassLoader.getSystemResources(path);
Properties properties = new Properties();
// 加载资源
while (urls.hasMoreElements()) {
properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
}
return loadMetadata(properties);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
}
}
获取需要自动加载的组件
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 获取EnableConfiguration注解的属性exclude
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取需要自动加载的组件
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 利用Set去除重复的组件
configurations = removeDuplicates(configurations);
// 获取排除属性 exclude, excludeName的值
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 根据exclude, excludeName排除Configuration
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 根据自定义的AutoConfigurationImportFilter排除Configuration
configurations = filter(configurations, autoConfigurationMetadata);
// 广播事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
获取需要自动加载的组件
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;
}
加载META-INF/spring-autoconfigure-metadata.properties的资源,并提取org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的值
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
// 获取EnableAutoConfiguration全名称
String factoryTypeName = factoryType.getName();
// 从spring-autoconfigure-metadata.properties获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
// 加载META-INF/spring-autoconfigure-metadata.properties的资源
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 从缓存中获取
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// 获取所有META-INF/spring-autoconfigure-metadata.properties的url
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
// 加载所有META-INF/spring-autoconfigure-metadata.properties资源并转为Map
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
// 放入缓存
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
将process步骤返回的conriguration给到Spring进行管理
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());
}
如果需要自己实现一个Starter
那只需要META-INF/spring-autoconfigure-metadata.properties的资源,并org.springframework.boot.autoconfigure.EnableAutoConfiguration的值为自己写的Configuration即可,一般框架会区分start包和真正实现的jar,然后由start包依赖真正实现的jar包
办公设备租赁,深圳惠源.