SpringBoot自动装配
小伙伴们,你们好,我是老寇,跟我一起学习SpringBoot 3.2.x源码
# 自动装配原理
// AutoConfigurationImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 步骤1
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 去重
configurations = removeDuplicates(configurations);
// 步骤2
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
// 步骤3
checkExcludedClasses(configurations, exclusions);
// 步骤4
configurations.removeAll(exclusions);
// 步骤5
configurations = getConfigurationClassFilter().filter(configurations);
// 步骤6
fireAutoConfigurationImportEvents(configurations, exclusions);
// 组装数据,由Spring注入IOC容器
return new AutoConfigurationEntry(configurations, exclusions);
}
- 从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 加载自动装配类
// AutoConfigurationImportSelector#getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
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;
}
- 加载需要排除的类,由 @EnableAutoConfiguration 注解的 exclude 和 excludeName ,以及配置文件中配置的 spring.autoconfigure.exclude 组成的集合
// AutoConfigurationImportSelector#getExclusions
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
Set<String> excluded = new LinkedHashSet<>();
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(asList(attributes, "excludeName"));
excluded.addAll(getExcludeAutoConfigurationsProperty());
return excluded;
}
// 配置文件
protected List<String> getExcludeAutoConfigurationsProperty() {
Environment environment = getEnvironment();
if (environment == null) {
return Collections.emptyList();
}
if (environment instanceof ConfigurableEnvironment) {
Binder binder = Binder.get(environment);
return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class)
.map(Arrays::asList)
.orElse(Collections.emptyList());
}
String[] excludes = environment.getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);
return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();
}
- 验证填写的排除的类是否存在
private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
List<String> invalidExcludes = new ArrayList<>(exclusions.size());
for (String exclusion : exclusions) {
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) {
invalidExcludes.add(exclusion);
}
}
if (!invalidExcludes.isEmpty()) {
handleInvalidExcludes(invalidExcludes);
}
}
排除相关自动装配的类
根据 AutoConfigurationImportFilter 过滤掉不符合的自动装配类,具体的做法是由 @ConditionalOnClass 、 @ConditionalOnBean 、 @ConditionalOnWebApplication 来判断,满足条件则返回,否则过滤掉
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
private ConfigurationClassFilter getConfigurationClassFilter() {
if (this.configurationClassFilter == null) {
List<AutoConfigurationImportFilter> filters = getAutoConfigurationImportFilters();
for (AutoConfigurationImportFilter filter : filters) {
invokeAwareMethods(filter);
}
this.configurationClassFilter = new ConfigurationClassFilter(this.beanClassLoader, filters);
}
return this.configurationClassFilter;
}
// getConfigurationClassFilter().filter(configurations);
List<String> filter(List<String> configurations) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean skipped = false;
for (AutoConfigurationImportFilter filter : this.filters) {
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
for (String candidate : candidates) {
if (candidate != null) {
result.add(candidate);
}
}
if (logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in "
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return result;
}
- 触发 AutoConfigurationImportEvent 事件,告诉 ConditionEvaluationReport 条件评估报告器记录符合条件和被排除的自动装配类
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);
}
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
if (!listeners.isEmpty()) {
AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
for (AutoConfigurationImportListener listener : listeners) {
invokeAwareMethods(listener);
listener.onAutoConfigurationImportEvent(event);
}
}
}
// ConditionEvaluationReportAutoConfigurationImportListener#onAutoConfigurationImportEvent
public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
if (this.beanFactory != null) {
ConditionEvaluationReport report = ConditionEvaluationReport.get(this.beanFactory);
report.recordEvaluationCandidates(event.getCandidateConfigurations());
report.recordExclusions(event.getExclusions());
}
}
- 最后Spring将符合条件的自动装配类导入IOC容器中
上次更新: 2024/03/21, 17:28:48