SpringBoot系列--自动装配原理1
一、自动配置原理
1、原理图
www.processon.com/diagraming/6072e...
2、源码入手
- SpringBootApplication
注解说明:
@Target(ElementType.TYPE)//设置当前注解可以标注在哪
@Retention(RetentionPolicy.RUNTIME)//标注注解的类编译以什么方式保留–运行时类,会被jvm加载
@Documented //生成java doc注解信息
@Inherited //是否会被继承
@SpringBootConfiguration //标注在某个类上,标识这是一个SpringBoot配置类
@EnableAutoConfiguration //标识这是一个配置类;配置类也是容器中的一个组件
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), //扫描包
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
FilterType:spring对外提供的扩展类,可以按照我们的意愿进行排除
AutoConfigurationExcludeFilter:排除所有配置类并且是自动配置类中里面的其中一个
我们进入注解—>@EnableAutoConfiguration
@AutoConfigurationPackage,作用是将当前配置类所在的包保存在BasePackages的Bean中,供Spring内部使用
@Import 关键注解
可以看到,在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,而EnableAutoConfigurationImportSelector 实现了DeferredImportSelectorSpring内部在解析@Import注解时会调用getAutoConfigurationEntry方法
如下代码的getCandidateConfigurations方法
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方法中的SpringFactoriesLoader.loadFactoryNames.loadFactoryNames.loadSpringFactories方法中进行扫描具有META-INF/spring.factories文件的jar包。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
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);
}
}
@EnableAutoConfiguration注解通过@SpringBootApplication被间接的标记在了Spring Boot的启动类上。在SpringApplication.run(…)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中
如下为SpringBoot自动配置原理图
本作品采用《CC 协议》,转载必须注明作者和本文链接