@TOCSpringBoot自动装配原理
Spring最明显的注解就是@SpringBootApplication这个注解,它是由@EnableAutoConfiguration、@SpringBootConfiguration、@ComponentScan三个注解实现。
@SpringBootApplication源码
@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 {
// ......
}
其中SpringBoot自动装配主要实现是@EnableAutoConfiguration这个注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
可以看到在这个注解上面还有一个@Import注解,并且传入了一个AutoConfigurationImportSelector.class,自动装配都是在这个类里面完成的。
protected static class AutoConfigurationEntry {
// 需要装配的配置文件
private final List<String> configurations;
// 不需要装配的配置
private final Set<String> exclusions;
private AutoConfigurationEntry() {
this.configurations = Collections.emptyList();
this.exclusions = Collections.emptySet();
}
AutoConfigurationEntry(Collection<String> configurations, Collection<String> exclusions) {
this.configurations = new ArrayList(configurations);
this.exclusions = new HashSet(exclusions);
}
public List<String> getConfigurations() {
return this.configurations;
}
public Set<String> getExclusions() {
return this.exclusions;
}
}
点进来可以看到,有一个叫做AutoConfigurationEntry这么一个实体类。
1、调用 getAutoConfigurationEntry()方法获取候选配置类的方法内容
protected AutoConfigurationImportSelector.AutoConfigurationEntry
getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// // 获取候选的配置类
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 根据情况,自动配置需要的配置类和不需要的配置了
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
// 返回最终需要的配置
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
在getCandidateConfigurations()方法里面调用localFactoryNames()方法并且传入一个EnableAutoConfiguration.class字节码以及ClassLoader类加载器传入
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
getSpringFactoriesLoaderFactoryClass()方法;返回EnableAutoConfiguration字节码;
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
// 返回的是EnableAutoConfiguration字节码对象
return EnableAutoConfiguration.class;
}
getBeanClassLoader()方法;返回ClassLoader类加载器;
protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
接下来,看看loadFactoryNames()方法做了什么
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
// 获取的EnableAutoConfiguration.class的权限定名
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
这个方法就是根据刚才的字节码文件和类加载器来找到候选的配置类,传递过来的字节码
最后通过 loadSpringFactories() 来获取到所有的配置类
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
// 去资源目录下找
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
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[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
// 加载完成放到缓存中
cache.put(classLoader, result);
// 返回加载到的配置类
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
这就是SpringBoot自动装配的简单过程。