SpringBoot -- 自动化装配源码
自动化装配源码
- @EnableAutoConfiguration 注解,开启自动配置的核心注解
- @AutoConfigurationPackage 注解
- AutoConfigurationImportSelector 类
- getAutoConfigurationEntry 方法
- getCandidateConfigurations 方法
- SpringFactoriesLoader
@EnableAutoConfiguration 注解,开启自动配置的核心注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
@EnableAutoConfiguration 包含了@AutoConfigurationPackage 注解和 @Import(AutoConfigurationImportSelector.class) 注解。
@AutoConfigurationPackage 注解
@AutoConfigurationPackage 通过 AutoConfigurationPackages.Registrar 将应用主类所在包及其子包下的所有组件扫描到Spring容器中。
重写这个方法就可以把包注册到spring 容器里面
有4个接口和一个注解都可以把对应类型放到容器里面,上文从源码来看是约定了一个接口,具体如何注册,看实现方式 AutoConfigurationPackages.register(registry, (new PackageImport(metadata)).getPackageName());
放到了定义map中
放到bean工厂,容器启动加载进去指的一说的是这个类,核心类 DefaultListableBeanFactory
从图中可以看到实现了 BeanFactory 接口和 ListableBeanFactory、ConfigurableListableBeanFactory、AutowireCapableBeanFactory 等多个接口。这个类是 Spring 容器的默认实现之一,是一个全功能的 Spring Bean 工厂,提供对 Bean 的完整管理,包括 Bean 的创建、定义、解析依赖、配置等功能
AutoConfigurationImportSelector 类
AutoConfigurationImportSelector 主要作用是收集和加载所有的自动配置类。
public class AutoConfigurationImportSelector extends ImportSelector {
@Override
public 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 方法
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 方法
getCandidateConfigurations 方法从 spring.factories 文件中加载所有的候选配置类:
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
SpringFactoriesLoader.loadFactoryNames 方法会读取 META-INF/spring.factories 文件中的配置,获取所有自动配置类的全限定名。
public abstract class SpringFactoriesLoader {
private static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, 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");
// 下面先别管
MultiValueMap<String, String> 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()) {
Map.Entry<?, ?> entry = (Map.Entry)var6.next();
String factoryClassName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
}
基本就结束了