springboot源码解读二-----(自动配置原理解析上)
源码注释环境
- jdk 1.8 +
- springboot 2.7.x
- idea 2022
- win 10
自动配置核心配置类 @EnableAutoConfiguration
EnableAutoConfiguration 中包含了两个注解:
# 里面包含一个 Import注解,作用是通过 AutoConfigurationPackages.Registrar.class 类把 AutoConfigurationPackage 所在的包信息注册进spring容器中
# 以供有需要的组件使用
@AutoConfigurationPackage
# 把 AutoConfigurationImportSelector.class 导入到项目中,
# AutoConfigurationImportSelector.class可以收集所有需要注册的类的信息,统一存储
@Import(AutoConfigurationImportSelector.class)
一: @AutoConfigurationPackage
@EnableAutoConfiguration 的作用就是注册一个基本包的bean信息。这个基本包信息后续有的程序或者插件可能会用到,基本包的信息通过: AutoConfigurationPackages.Registrar.class 注册。
// 源注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 把 AutoConfigurationPackages.Registrar.class 导入项目中,使用 AutoConfigurationPackages.Registrar.class可以
// 注册基本包的信息,以供其他插件使用
// 基本包信息: basepackage 默认情况下,程序会取 使用 @AutoConfigurationPackage 注解的包的地址,因为 @AutoConfigurationPackage 是
// 复合在 @SpringBootApplication 使用的,所以基本包的信息就是 使用@SpringBootApplication 注解的包的信息。
// 【总结】 @AutoConfigurationPackage 其实就是把AutoConfigurationPackages.Registrar.class注入程序,并通过该类把程序包的bean注册进map。
// key为 "org.springframework.boot.autoconfigure.AutoConfigurationPackages" value 为 BasePackagesBeanDefinition对象(里面存储了 basePackage
// 的信息)
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
/**
* Base packages that should be registered with {@link AutoConfigurationPackages}.
* <p>
* Use {@link #basePackageClasses} for a type-safe alternative to String-based package
* names.
* @return the back package names
* @since 2.3.0
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages} for specifying the packages to be
* registered with {@link AutoConfigurationPackages}.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return the base package classes
* @since 2.3.0
*/
Class<?>[] basePackageClasses() default {};
}
-
AutoConfigurationPackages.Registrar.class
/** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. */ static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { // metadata 为 注解的元信息,registry为 bean 默认bean注册表(bean注册中心) // @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // new PackageImports(metadata).getPackageNames().toArray(new String[0]) 获取注解所在的包。例如: com.ruoyi // 把该包信息注册为bean // 调用 register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0])); } @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImports(metadata)); } }
-
register 方法
// registry bean注册表(注册中心) packageNames 包名,例如: "com.ruoyi" // BEAN 即为 basePackage注册的key 值。BEAN: "org.springframework.boot.autoconfigure.AutoConfigurationPackages" public static void register(BeanDefinitionRegistry registry, String... packageNames) { if (registry.containsBeanDefinition(BEAN)) { BasePackagesBeanDefinition beanDefinition = (BasePackagesBeanDefinition) registry.getBeanDefinition(BEAN); beanDefinition.addBasePackages(packageNames); } else { // 第一次走这个逻辑,把basePackage信息注册到一个map,key: BEAN 的值,value为 basePackage的 beanDefinition // BeanDefinition描述了一个bean实例,它具有属性值、构造函数参数值以及具体实现提供的进一步信息。 registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames)); } }
-
DefaultListableBeanFactory的 方法: registerBeanDefinition
//--------------------------------------------------------------------- // Implementation of BeanDefinitionRegistry interface //--------------------------------------------------------------------- // 把 beanName通过beanDefinition携带的bean信息注册。 @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { // 判断有没有已经创建的bean, 有的话,需要加入进来,并把 beanName 注册 进来 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // 直接把 beanName 注册进来,放到一个map中,key beanName ,value: beanDefinition // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); // 把 beanName 的key值存放金 一个 list中 this.beanDefinitionNames.add(beanName); removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } else if (isConfigurationFrozen()) { clearByTypeCache(); } }
【【功能总结】】: @EnableAutoConfiguration 的作用就是注册一个基本包的bean信息。这个基本包信息后续有的程序或者插件可能会用到,基本包的信息通过: AutoConfigurationPackages.Registrar.class 注册。
【【流程总结】】
- 通过 AutoConfigurationPackages.Registrar.class 调用 registerBeanDefinitions 方法
- registerBeanDefinitions 方法中调用 AutoConfigurationPackages 的 register 方法
- register 走 第一次走 else 语句 调用 DefaultListableBeanFactory 的 registerBeanDefinition 方法 完成basePackage bean信息的注册
- registerBeanDefinition 方法会把bean信息存进 registerBeanDefinition 的 this.beanDefinitionMap 和 this.beanDefinitionNames中。
二: @Import(AutoConfigurationImportSelector.class)
@Import(AutoConfigurationImportSelector.class) 的作用就是把springboot以及第三方工具中所有需要自动配置的类的完成路径名导入程序中,以供后面使用。
-
AutoConfigurationGroup.class (为AutoConfigurationImportSelector中的静态子类) 中有个核心方法 process
springboot最终就是调用 process 来收集 所有的自动配置的类,并过滤掉那些没有用到的配置。
private static class AutoConfigurationGroup
implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
// 所有 自动配置的类, key:完整类名 value: 该注解的元信息
private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
// 所有自动配置类的列表,AutoConfigurationEntry 中存储所有自动配置类的完整类名。
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
private ClassLoader beanClassLoader;
private BeanFactory beanFactory;
private ResourceLoader resourceLoader;
private AutoConfigurationMetadata autoConfigurationMetadata;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
// 核心 方法
// 收集 所有需要自动配置的 类
// annotationMetadata 注解元信息 deferredImportSelector 使用指定的DeferredImportSelector处理导入类的AnnotationMetadata。
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
// 读取 所有组件的 spring.factories 中 所有的自动配置类
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
// 把自动配置实体加入 自动配置表
this.autoConfigurationEntries.add(autoConfigurationEntry);
// 取出所有的自动配置类名,并加入 entries map中
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
// 过滤 不需要的 配置类,并把自动配置的类进行排序,按照 @Order注解排序
@Override
public Iterable<Entry> selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
Set<String> allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
processedConfigurations.removeAll(allExclusions);
// 按照 @Order 进行排序
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
if (this.autoConfigurationMetadata == null) {
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
}
return this.autoConfigurationMetadata;
}
private List<String> sortAutoConfigurations(Set<String> configurations,
AutoConfigurationMetadata autoConfigurationMetadata) {
return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
.getInPriorityOrder(configurations);
}
private MetadataReaderFactory getMetadataReaderFactory() {
try {
return this.beanFactory.getBean(SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
MetadataReaderFactory.class);
}
catch (NoSuchBeanDefinitionException ex) {
return new CachingMetadataReaderFactory(this.resourceLoader);
}
}
}