SringBoot自动装配过程分析

本文贴出的众多代码,版本来源为SpringBoot1.5.10,Spring4.3.14,如果两端代码中间有调用关系,可以通过查找上方的中文注释来快速定位

SpringBootStarter自动装配过程

在项目中我们一般使用 @SpringBootApplication 来作为SpringBoot项目的启动类,SpringBoot采用约定大于配置的思想来进行类的注入,使得配置文件大量简化,服务构建更为快捷

那么SpringBoot是如何进行自动装配的呢?根据SpringBoot1.5.10的源码,可以看到 @SpringBootApplication引用了 @SpringBootConfiguration进行配置

1
2
3
4
5
6
7
8
9
10
11
12
@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 {
//省略部分内容
}

@SpringBootConfiguration接口使用 @Configuration进行修饰

1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration//允许注入的代码
public @interface SpringBootConfiguration {

}

也就是读取配置文件并进行注入的工作是由Spring的Configuration实现的

复习一下Configuration的实现步骤

IOC容器启动时,作为一个Component参与到其中

1
2
3
4
5
6
7
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component//Configuration是一个Component,从而在IOC容器装配的时候运行
public @interface Configuration {
//省略部分内容
}

IOC容器生成后,进行再一步的扩展处理

由Spring IOC容器中的 AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext高级上下文容器中生成IOC容器后进行修改

AnnotationConfigWebApplicationContext继承GenericApplicationContext再继承AbstractApplicationContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
//省略部分内容
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
// 在这里对IOC容器进行再一次处理,SpringBoot的自动装配就是在这个步骤里实现
invokeBeanFactoryPostProcessors(beanFactory);
//省略部分代码
}catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
//省略部分内容
}

针对IOC容器中的Configuration部分进行再次处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
//省略部分内容
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//在此增强
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
//省略部分内容
}

针对IOC容器中的Configuration部分进行再次处理

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
class PostProcessorRegistrationDelegate {
//省略部分内容
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();

if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//对BeanFactory进行深加工
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
}
else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//省略部分内容
}
//省略部分内容
}

处理前的校验和状态锁定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanClassLoaderAware {
//省略部分内容
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.postProcessBeanDefinitionRegistryCalled) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called for this post-processor");
}
if (this.postProcessBeanFactoryCalled) {
throw new IllegalStateException(
"postProcessBeanFactory already called for this post-processor");
}
this.postProcessBeanDefinitionRegistryCalled = true;
//在这里进行SpringBoot约定的默认配置
processConfigBeanDefinitions(registry);
}
//省略部分内容
}

对存在Configuration修饰JAVA类的BeanDefinition进行修改

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
40
41
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanClassLoaderAware {
//省略部分内容
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
Set<BeanDefinitionHolder> configCandidates = new LinkedHashSet<BeanDefinitionHolder>();
for (String beanName : registry.getBeanDefinitionNames()) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassBeanDefinitionReader.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}

// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}

// Populate a new configuration model by parsing each @Configuration classes
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter);
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parser.parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parser.parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("Failed to load bean class: " + bd.getBeanClassName(), ex);
}
}
parser.validate();

// Read the model and create bean definitions based on its content
ConfigurationClassBeanDefinitionReader reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.problemReporter, this.metadataReaderFactory);
reader.loadBeanDefinitions(parser.getConfigurationClasses());
}
//省略部分内容
}

这一步我们讲述了自动装配是如何发生的,下面讲一下自动装配发生前,目标类和配置类是如何进行准备的

筛选需要装配的类和配置

再次回到SpringBootApplication,我们看另外一个接口@EnableAutoConfiguration

1
2
3
4
5
6
7
8
9
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage//目标类
@Import(EnableAutoConfigurationImportSelector.class)//配置类
public @interface EnableAutoConfiguration {
}

AutoConfigurationPackage,根据配置的路径扫描需要进程自动配置的目标类

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

}

EnableAutoConfigurationImportSelector,用于返回配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Deprecated
public class EnableAutoConfigurationImportSelector
extends AutoConfigurationImportSelector {

@Override
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
return getEnvironment().getProperty(
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
true);
}
return true;
}

}

通过EnableAutoConfigurationImportSelector的父类AutoConfigurationImportSelector看扫描配置了的步骤

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
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {

public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
//省略部分内容
}

获取配置的详细代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
//省略部分内容
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;
}
//省略部分内容
}

而这个具体的获取方法是使用的spring的工厂,加载项目路径下的所有spring.factories文件,返回配置类

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
public abstract class SpringFactoriesLoader {

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
//省略部分内容
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
//省略部分内容
}

至此目标类和目标配置以及准备完毕