springboot源码解读二-----(自动配置原理解析上)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

源码注释环境

  • 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信息注册到一个mapkey 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 注册。

【【流程总结】】

  1. 通过 AutoConfigurationPackages.Registrar.class 调用 registerBeanDefinitions 方法
  2. registerBeanDefinitions 方法中调用 AutoConfigurationPackages 的 register 方法
  3. register 走 第一次走 else 语句 调用 DefaultListableBeanFactory 的 registerBeanDefinition 方法 完成basePackage bean信息的注册
  4. 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);
			}
		}

	}

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring