自动配置过程
备注:关键代码是注释标记了debug主线的
1.使用 @EnableAutoConfiguration 启用自动配置
1.1 程序入口
//debug主线
@SpringBootApplication()
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
1.2 启动自动配置注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
//debug主线
@EnableAutoConfiguration
public @interface SpringBootApplication {
//omit...
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
//debug主线
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
//omit...
}
2.从 spring-boot-autoconfigure.jar 文件的 AutoConfiguration.imports 中获取所有自动配置类
//自动配置导入选择器
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//omit...
//为什么是这个方法?因为AutoConfigurationImportSelector实现了DeferredImportSelector extends ImportSelector,
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//如果没有启动自动配置
if(!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//debug主线:获取自动配置类
AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if(!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
//获取启动类注解属性
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//debug主线:从META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件获取所有全限定自动配置类名
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 AutoConfigurationEntry(configurations, exclusions);
}
}
//omit...
}
//自动配置导入选择器
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//omit...
protected List < String > getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//debug主线:加载自动配置类,并将它们作为字符串列表存储在 configurations 变量中
List < String > configurations = ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).getCandidates();
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
//omit...
}
//提供对这些候选自动配置类的迭代访问
public final class ImportCandidates implements Iterable < String > {
//omit...
public static ImportCandidates load(Class <? > annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
//最终得到:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
//此文件包含了146个开发常用的AutoConfiguration类,
String location = String.format("META-INF/spring/%s.imports", annotation.getName());
//从你的spring-boot-autoconfigure-3.1.1.jar下面classpath找到这个位置
Enumeration < URL > urls = findUrlsInClasspath(classLoaderToUse, location);
List < String > importCandidates = new ArrayList();
//所有的自动配置类全限定类名
while(urls.hasMoreElements()) {
URL url = (URL) urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
//omit...
}
3.从自动配置类集合中移除启动类中排除的类
//自动配置导入选择器
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//omit...
protected 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);
//支线:获取你启动类注解添加的排除类属性,@SpringBootApplication(exclude = ...,excludeName = ...)
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 AutoConfigurationEntry(configurations, exclusions);
}
}
//omit...
}
4.过滤掉不符合 @ConditionalOnXXX 相关注解条件的自动配置类
//自动配置导入选择器
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//omit...
protected 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);
//支线:从所需的自动配置类集合中过滤掉那些带有不满足 @ConditionalOnXXX 相关注解条件的自动配置类
/**
* 这样做是因为只有在你使用了相关组件时,才会为你引入相应的自动配置。
* 举个例子:在自动配置类集合中存在一个叫RabbitAutoConfiguration的自动配置类,并且该类上存在 @ConditionalOnClass({RabbitTemplate.class, Channel.class}) 注解。
* 如果你想使用 Rabbit 组件,那么你需要在 Maven 中引入 rabbitmq-starter 依赖。引入了 rabbitmq-starter 之后,你还需要将 RabbitTemplate 作为 Bean 加载到 Spring 容器中。
* 一旦容器中存在了 RabbitTemplate,那么这个自动配置类就会自动生效,
* 一个空项目自然不会引入这么多外部starter,所以你最终生效的自动配置类146个可能过滤后就只有不到30个会注入到容器中
*/
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}
//omit...
}
5.将符合条件的自动配置类注入到单例对象 ConcurrentHashMap 中
//自动配置导入选择器
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//omit...
protected 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);
//debug主线:触发自动导入事件
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}
/**
* 触发自动配置导入事件,并通知所有的自动配置导入监听器。
*
* @param configurations 自动配置类列表
* @param exclusions 排除的自动配置类列表
*/
private void fireAutoConfigurationImportEvents(List < String > configurations, Set < String > exclusions) {
// 获取所有的自动配置导入监听器
List < AutoConfigurationImportListener > listeners = getAutoConfigurationImportListeners();
// 如果监听器列表不为空
if(!listeners.isEmpty()) {
// 创建一个 AutoConfigurationImportEvent 事件对象,包含当前对象(即 this)、自动配置类列表和排除的自动配置类列表
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
// 遍历监听器列表
for(AutoConfigurationImportListener listener: listeners) {
// 对监听器进行调用前的准备操作(如调用相关的 Aware 方法)
invokeAwareMethods(listener);
//debug主线:调用每个监听器的 onAutoConfigurationImportEvent 方法,将事件对象作为参数传递给监听器,通知其处理自动配置导入事件
listener.onAutoConfigurationImportEvent(event);
}
}
}
//omit...
}
/**
* 自动配置导入监听器接口
*/
@FunctionalInterface
public interface AutoConfigurationImportListener extends EventListener {
/**
* debug主线:处理自动配置导入事件。
* @param event 要响应的事件
*/
void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event);
}
/**
* ConditionEvaluationReportAutoConfigurationImportListener 类是一个实现了 AutoConfigurationImportListener 接口和 BeanFactoryAware 接口的条件评估报告自动配置导入监听器。
*/
class ConditionEvaluationReportAutoConfigurationImportListener implements AutoConfigurationImportListener, BeanFactoryAware {
//omit...
private ConfigurableListableBeanFactory beanFactory;
/**
* 处理自动配置导入事件。
* @param event 要响应的事件
*/
@Override
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
// 检查是否已经设置了 beanFactory
if (this.beanFactory != null) {
// debug主线:获取条件评估报告实例
ConditionEvaluationReport report = ConditionEvaluationReport.get(this.beanFactory);
// 记录评估候选配置
report.recordEvaluationCandidates(event.getCandidateConfigurations());
// 记录排除的自动配置
report.recordExclusions(event.getExclusions());
}
}
//omit...
}
public final class ConditionEvaluationReport {
/**
* 根据指定的 BeanFactory 获取 ConditionEvaluationReport。
* @param beanFactory BeanFactory 实例
* @return 存在的 ConditionEvaluationReport 实例,如果不存在则创建一个新实例
*/
public static ConditionEvaluationReport get(ConfigurableListableBeanFactory beanFactory) {
synchronized(beanFactory) {
ConditionEvaluationReport report;
// 检查是否已经存在单例实例
if(beanFactory.containsSingleton(BEAN_NAME)) {
// 如果存在,则获取现有的 ConditionEvaluationReport 实例
report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
} else {
// 如果不存在,则创建一个新的 ConditionEvaluationReport 实例
report = new ConditionEvaluationReport();
// debug主线:将新实例注册为单例实例
beanFactory.registerSingleton(BEAN_NAME, report);
}
// 定位父级 BeanFactory 的 ConditionEvaluationReport
locateParent(beanFactory.getParentBeanFactory(), report);
// 返回 ConditionEvaluationReport 实例
return report;
}
}
// 省略其他代码...
}
}
/**
* SingletonBeanRegistry 接口定义了管理单例 Bean 的方法。
*/
public interface SingletonBeanRegistry {
/**
* debug主线:注册一个单例对象。
* @param beanName Bean 的名称
* @param singletonObject 单例对象实例
*/
void registerSingleton(String beanName, Object singletonObject);
/**
* 获取指定名称的单例对象。
* @param beanName Bean 的名称
* @return 单例对象实例,如果不存在则返回 null
*/
@Nullable
Object getSingleton(String beanName);
/**
* 检查是否存在指定名称的单例对象。
* @param beanName Bean 的名称
* @return 如果存在指定名称的单例对象则返回 true,否则返回 false
*/
boolean containsSingleton(String beanName);
/**
* 获取所有注册的单例 Bean 的名称。
* @return 单例 Bean 的名称数组
*/
String[] getSingletonNames();
/**
* 获取注册的单例 Bean 的数量。
* @return 单例 Bean 的数量
*/
int getSingletonCount();
/**
* 获取单例对象的互斥锁。
* @return 单例对象的互斥锁
*/
Object getSingletonMutex();
}
/**
* DefaultListableBeanFactory 是一个实现了 ConfigurableListableBeanFactory、BeanDefinitionRegistry 接口的类,
* 继承自 AbstractAutowireCapableBeanFactory,用于注册单例对象的默认可列举 Bean 工厂。
*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// 省略其他代码...
/**
* 注册一个单例对象。
* @param beanName Bean 的名称
* @param singletonObject 单例对象实例
* @throws IllegalStateException 如果已存在同名的单例对象则抛出异常
*/
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 主线debug:调用父类DefaultSingletonBeanRegistry的 registerSingleton 方法,将单例对象注册到父类的 singletonObjects 中
super.registerSingleton(beanName, singletonObject);
// 更新手动注册的单例名称集合
this.updateManualSingletonNames(set -> {
set.add(beanName);
}, set -> {
// 检查该 Bean 名称是否已经存在于 beanDefinitionMap 中,如果存在则返回 false
return !this.beanDefinitionMap.containsKey(beanName);
});
// 清除类型缓存
this.clearByTypeCache();
}
// 省略其他代码...
}
/**
* DefaultSingletonBeanRegistry 是一个实现了 SingletonBeanRegistry 接口的类,
* 继承自 SimpleAliasRegistry,用于注册和管理单例 Bean 的默认单例 Bean 注册表。
*/
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// 省略其他代码...
//存储单例对象的映射
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
/**
* 注册一个单例对象。
* @param beanName Bean 的名称
* @param singletonObject 单例对象实例
* @throws IllegalStateException 如果已存在同名的单例对象则抛出异常
*/
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 检查 beanName 是否为 null
Assert.notNull(beanName, "Bean name must not be null");
// 检查 singletonObject 是否为 null
Assert.notNull(singletonObject, "Singleton object must not be null");
// 对 singletonObjects 进行同步操作
synchronized (this.singletonObjects) {
// 检查是否已存在同名的单例对象
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
// 如果已存在同名的单例对象,则抛出 IllegalStateException 异常
throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
} else {
// 主线debug:否则将单例对象添加到 singletonObjects 中
this.addSingleton(beanName, singletonObject);
}
}
}
/**
* 添加一个单例对象到单例对象映射中。
* @param beanName Bean 的名称
* @param singletonObject 单例对象实例
*/
protected void addSingleton(String beanName, Object singletonObject) {
// 对 singletonObjects 进行同步操作
synchronized (this.singletonObjects) {
// 将单例对象添加到 singletonObjects 中
this.singletonObjects.put(beanName, singletonObject);
// 从 singletonFactories 中移除对应的单例工厂对象
this.singletonFactories.remove(beanName);
// 从 earlySingletonObjects 中移除对应的早期单例对象
// 这一步是为了解决循环依赖的三级缓存问题
// 详细原理可参考 Spring 的循环依赖解决机制
this.earlySingletonObjects.remove(beanName);
// 将 beanName 添加到 registeredSingletons 中,标记该 Bean 已注册为单例
this.registeredSingletons.add(beanName);
}
}
// 省略其他代码...
}
至此SpringBoot应用上下文创建阶段之自动配置类:从文件中读取、筛选、到加载到ConcurrentHashMap的代码已经跑完,
剩下的就是SpringBootApplication.run方法里面的应用上下文刷新阶段,可查看启动程序run方法里面的this.refreshContext(context);方法,跟到AbstractApplicationContext.refresh()方法,包括创建 Web 服务器、加载应用程序的配置、bean工厂处理、初始化各种组件