spring源码阅读(二)——自动配置

之前的文章中分析了springboot启动的大概流程,那些只是冰山一角,最关键的refresh()只是一笔带过。这篇文章中将会提到refreh的部分过程。另外之前的文章也写过springboot如何自定义starter ,这篇文章将简单分析一下其原理。

spring源码阅读(一)中说到的第四步:spring容器前置处理中,将我们的启动类HelloWorldApplication.class当做参数调用load(),使其加载到beanDefinitionMap中。

1
2
3
4
5
6
7
8
9
10
11
12
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
return 0;
}

这次我们再跟进去看看,最后调用的地方是AnnotatedBeanDefinitionReader.javadoRegisterBean()方法。进入断点查看,我们的启动类最终被包装成AnnotatedGenericBeanDefinition,后期的启动类的处理都基于该对象了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 将我们的启动类包装成 AnnotatedGenericBeanDefinition 对象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 将我们的启动类加载到 beanDefinitionMap 中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

@EnableAutoConfiguration

@SpringBootApplication注解中包含了自动配置入口的注解。

1
2
3
4
5
6
7
8
9
@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 {}

跟进去看一下,又包含了@AutoConfigurationPackage自动配置包注解

1
2
3
4
5
6
7
8
9
10
11
@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 {};
}
@AutoConfigurationPackage

跟进@AutoConfigurationPackage,它导入了AutoConfigurationPackages.Registrar.class`

1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}

跟进它 import 的这个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 默认将会扫描@SpringBootApplication标注的主配置类所在的包及其子包下所有组件
register(registry, new PackageImport(metadata).getPackageName());
}

@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}

}

如果我们将断点打在registerBeanDefinitions方法里,可以看见这一步是refresh()过程中的invokeBeanFactoryPostProcessors(beanFactory)方法在调用。

执行完后 registry 中 beanDefinitionMap 将多一个 AutoConfigurationPackages

image.png

@Import(AutoConfigurationImportSelector.class)

导入哪些组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。进入此类,有一个关键方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
}

如果在这个方法里打断点,可以发现,这里也是 refresh()过程中的invokeBeanFactoryPostProcessors(beanFactory)方法在调用。

接着重点看下getCandidateConfigurations()方法,它从META-INF/spring.factories文件中取出EnableAutoConfiguration对应的所有 value。因此,如果要实现自动配置功能,需要将我们的自动配置类写在 factories 文件下的 org.springframework.boot.autoconfigure.EnableAutoConfiguration属性中

1
2
3
4
5
6
7
8
9
10
11
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;
}

protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}

更详细的 refresh 过程,将在下一篇文章中分析。