本文主要是介绍揭密springboot自动装配(2)--AutoConfigurationImportSelector,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
我们从启动类里的@SpringBootApplication注解开始
里面有三个主要注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
这里自动装配的主要注解是@EnableAutoConfiguration这个,我们跟进去看看
会发现这里面有引入我们上章提到的神秘东东AutoConfigurationImportSelector
继续跟进AutoConfigurationImportSelector一探究竟,它是实现DeferredImportSelector,这个里面继承了ImportSelector
我们来看看他的selectImports方法实现
@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
这里面我们关注getAutoConfigurationEntry继续跟进去
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}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 new AutoConfigurationEntry(configurations, exclusions);}
继续跟进getCandidateConfigurations这个方法
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;}
到这里你会发现有这么句话No auto configuration classes found in META-INF/spring.factories,
META-INF/spring.factories这个文件是不是有点熟悉,先放着,继续跟进就会明白了
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {String factoryTypeName = factoryType.getName();return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");LinkedMultiValueMap result = new LinkedMultiValueMap();while(urls.hasMoreElements()) {URL url = (URL)urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Entry<?, ?> entry = (Entry)var6.next();String factoryTypeName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryImplementationName = var9[var11];result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}}}
直到这里你会发现,他就是加载了所有META-INF/spring.factories文件下的数据,我们随便点开一个META-INF/spring.factories看看
这里面就有很多需要自动装配的key-value对,到这里我们就应该能猜到大概实现了
这里loadFactoryNames就是获取对应EnableAutoConfiguration.class也就是对应上面spring.factories文件里的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的所有value值也就是class路径
protected Class<?> getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}
我们重新回到selectImports方法
到这里我们就很清楚这里返回的就是所有在spring.factories文件里key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的所有value值class路径,印证上一章中的例子,我们下面回顾下:
同样这里是不是可以启发我们,将配置类写在META-INF/spring.factories文件里,然后key写为
org.springframework.boot.autoconfigure.EnableAutoConfiguration
是不是也可以自动帮我们给装配进去,例如下面这样我们在自己项目中创建META-INF/spring.factories,我们自动装配UserA
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.service.UserA
这样我们也是一样可以在spring容器中可以拿到我们的UserA;
ok,基本的实现流程我们已经了解大概了,那到这里应该还是会有个疑问,哪个地方调用selectImports方法?
下章我们就这个问题进行分析
这篇关于揭密springboot自动装配(2)--AutoConfigurationImportSelector的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!