一、入口
@SpringBootApplication // 自动装配注解
public class AutoConfigurationApplication {
public static void main(String[] args) {
SpringApplication.run(AutoConfigurationApplication.class, args);
}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited // 用来修饰注解,代表可继承
@SpringBootConfiguration // 标识配置类,套用了Spring @Configuration
@EnableAutoConfiguration // 自动配置核心
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}
@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 {};
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class}) // 关键类
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
二、Registrar
item --> @Component标识
demoConfig --> @Configuration标识
myTest --> @Bean标识
// 就是包名.类名
private static final String BEAN = AutoConfigurationPackages.class.getName();
// 没有则注册
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
AutoConfigurationPackages.BasePackagesBeanDefinition beanDefinition = (AutoConfigurationPackages.BasePackagesBeanDefinition)registry.getBeanDefinition(BEAN);
beanDefinition.addBasePackages(packageNames);
} else {
registry.registerBeanDefinition(BEAN, new AutoConfigurationPackages.BasePackagesBeanDefinition(packageNames));
}
}
注册Bean的方法,随便点一个实现类看
用Map管理的,没有就put一个
/**
并发安全集合,put操作算是添加了
以下是gpt回答:
beanDefinitionMap 是 Spring 容器中存储 Bean 定义信息的一个数据结构,
它是一个 ConcurrentHashMap 对象,用于存储 BeanDefinition 对象,
其中键为 Bean 的名称,值为 Bean 的定义。Spring 容器会在启动时扫描所有的配置类,
解析其中的 Bean 定义信息,并将其存储到 beanDefinitionMap 中,以便后续的实例化
和依赖注入。通过 beanDefinitionMap,Spring 容器可以快速地查找 Bean 的定义信息,
比如是否存在、是否是单例、是否延迟初始化等等。
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(64);
三、AutoConfigurationImportSelector
核心方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// getAutoConfigurationEntry 点进去断点
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.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);
// exclude声明的类排除
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 可以点进去看看,没必要断点了,configurations去掉排除的类
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 去除不必要的配置类,见四解析
configurations = this.getConfigurationClassFilter().filter(configurations);
/**
gpt对此方法解释:
这段代码的作用是通知所有的AutoConfigurationImportListener,
即自动配置导入监听器,当前应用程序已经导入了哪些自动配置类以及排除了哪些
自动配置类。这个方法会创建一个AutoConfigurationImportEvent事件,
然后通过调用每个监听器的onAutoConfigurationImportEvent方法,将该事件
传递给监听器。在事件传递之前,该方法还会通过调用invokeAwareMethods方法,
将当前的BeanFactory和ClassLoader等信息注入到每个监听器中。
*/
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 断点进去,读取META-INF/spring.factories文件
List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
/**
load()断点进去
读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
*/
ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor 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;
}
META-INF/spring.factories
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
四、filter(configurations)
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
Iterator var6 = this.filters.iterator();
int i;
while(var6.hasNext()) {
AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var6.next();
// 核心方法
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for(i = 0; i < match.length; ++i) {
if (!match[i]) {
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
} else {
List<String> result = new ArrayList(candidates.length);
String[] var12 = candidates;
int var14 = candidates.length;
for(i = 0; i < var14; ++i) {
String candidate = var12[i];
if (candidate != null) {
result.add(candidate);
}
}
if (AutoConfigurationImportSelector.logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
AutoConfigurationImportSelector.logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return result;
}
}
}
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
// report 记录用的
ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
// 核心方法
ConditionOutcome[] outcomes = this.getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
boolean[] match = new boolean[outcomes.length];
for(int i = 0; i < outcomes.length; ++i) {
match[i] = outcomes[i] == null || outcomes[i].isMatch();
if (!match[i] && outcomes[i] != null) {
this.logOutcome(autoConfigurationClasses[i], outcomes[i]);
if (report != null) {
report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
}
}
}
return match;
}
OnClassCondition类
protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
// 准备多线程判断了
if (autoConfigurationClasses.length > 1 && Runtime.getRuntime().availableProcessors() > 1) {
return this.resolveOutcomesThreaded(autoConfigurationClasses, autoConfigurationMetadata);
} else {
OnClassCondition.OutcomesResolver outcomesResolver = new OnClassCondition.StandardOutcomesResolver(autoConfigurationClasses, 0, autoConfigurationClasses.length, autoConfigurationMetadata, this.getBeanClassLoader());
return outcomesResolver.resolveOutcomes();
}
}
// 两个线程开搞
private ConditionOutcome[] resolveOutcomesThreaded(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
int split = autoConfigurationClasses.length / 2;
OnClassCondition.OutcomesResolver firstHalfResolver = this.createOutcomesResolver(autoConfigurationClasses, 0, split, autoConfigurationMetadata);
OnClassCondition.OutcomesResolver secondHalfResolver = new OnClassCondition.StandardOutcomesResolver(autoConfigurationClasses, split, autoConfigurationClasses.length, autoConfigurationMetadata, this.getBeanClassLoader());
// 核心方法,最后一层,不套娃了
ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
return outcomes;
}
OnClassCondition类
五、常用的Conditional注解:
@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
总结
1,先从
META-INF/spring.factories
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 加载配置类
2,再找到排除掉的类
3,排除掉没引入依赖的类
(反射jar包类全路径,引入了就装配,没引入的不装配)
4,加载的顺序是要被记录的