[Frame source code] Automatic configuration source code analysis of SpringBoot core source code interpretation

insert image description here

Before SpringBoot became popular, programmers mostly used SSM框架integration for WEB back-end development. This method is very cumbersome, requiring manual introduction of a large number of packages and configuration of many XML files, and it takes a long time just to build the environment.

Based on the cumbersome xml configuration in this kind of SSM, SpringBoot was later derived. The automatic loading in SpringBoot greatly simplifies the developer's information about configuration.

Question: What is SpringBoot auto-configuration?

  • When the spring container starts, some auto-configuration classes are @Conditionalauto-assembled through annotations in the IOC container
  • There is no need to manually inject, which simplifies development and saves tedious configuration
  • The related work of automatic configuration is on @SpringBootApplicationthis annotation

Let's take a look at @SpringBootApplicationthis annotation.

@Target({
    
    ElementType.TYPE})  //注解的作用范围,用在类,接口,注解等上面
@Retention(RetentionPolicy.RUNTIME) //注解生命周期,runtime,保留在运行时期
@Documented //可以被文档化
@Inherited //可以被子类继承
@SpringBootConfiguration  //里面是@Configuration属于配置类
@EnableAutoConfiguration  //启动自动配置功能
//配置扫描包
@ComponentScan(
    excludeFilters = {
    
    @Filter(
    type = FilterType.CUSTOM,
    classes = {
    
    TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {
    
    AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication

@SpringBootApplication is a composite annotation consisting of several core annotations.

  • @SpringBootConfiguration
    • Inside is @Configuration, which represents a configuration class, indicating that the main program class is also a configuration class
  • @EnableAutoConfiguration
    • @AutoConfigurationPackage imports all components under a specified package into the container
    • There is an @Import({Registrar.class}) annotation in the @AutoConfigurationPackage annotation, and the automatic configuration package is done through this.
  • @ComponentScan
    • Specify which components to scan, the default is to scan the package where the main program is located and its subpackages

Its core lies in @EnableAutoConfigurationthis annotation, which contains the class information for loading automatic configuration.

@EnableAutoConfiguration annotation core content

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationImportSelector.class) //通过import导入满足条件的bean,并加载到spring的ioc容器里面
public @interface EnableAutoConfiguration 

@AutoConfigurationPackage annotation core content

  • The role of Registrar is to scan packages. By default, all classes in the package and subpackages where the main class is located are scanned into the container.
  • So why do you need to put the main class in the outermost directory when developing a springboot project, otherwise the correct annotation class will not be found
@Import(AutoConfigurationPackages.Registrar.class) //把Registrar导入到spring容器里面

The core logic is this logic, and we will breakpoint for debugging later.

		//获取主程序所在的目录为位置,metadata是元注解信息
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata,
				BeanDefinitionRegistry registry) {
    
    
			register(registry, new PackageImport(metadata).getPackageName());
		}

Next, let's take a look at @Import(AutoConfigurationImportSelector.class)what operations have been done in this. Its core is to import beans that meet the conditions through import, and load the classes that meet @Configuration in the springboot application into the spring ioc container

	//用于实现动态注册Bean的功能,【批量】导入对象到容器里,根据条件动态地选择需要注册的Bean,并加入Spring容器
  //实现ImportSelector接口,这个接口的selectImports方法会返回一个String数组,数组中的值就是要添加的组件的全类名
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
    
    
		if (!isEnabled(annotationMetadata)) {
    
    
			return NO_IMPORTS;
		}
    //加载元数据信息
		AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
    //获取需要自动装载的类的信息
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
				autoConfigurationMetadata, annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

ok, let's take a look at getAutoConfigurationEntry()the logic of this method. This method is mainly to obtain auto-configured entries according to the specified annotation metadata.

protected AutoConfigurationEntry getAutoConfigurationEntry(
			AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
    
    
  	//判断是否启用了自动配置
		if (!isEnabled(annotationMetadata)) {
    
    
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
  	//获取候选自动配置类列表
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
  	//去除重复的自动配置类
		configurations = removeDuplicates(configurations);
  	//获取需要排除的自动配置类列表
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
  	//检查是否存在需要排除的自动配置类
		checkExcludedClasses(configurations, exclusions);
  	//将需要排除的类从自动配置类列表中移除
		configurations.removeAll(exclusions);
  	//获取配置类过滤器,对候选自动配置类列表进行过滤
		configurations = filter(configurations, autoConfigurationMetadata);
  	//触发自动配置导入事件,并返回一个新的自动配置条目
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

Let's take a look at getCandidateConfigurations()the core logic here, which is to go to META-INF/spring.factoriesthis file to pull all the configuration information.

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
    
    
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
	public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

Ok, let's debug and walk down the source code process.

insert image description here
insert image description here
insert image description here
insert image description hereinsert image description here
insert image description hereinsert image description here

insert image description here
insert image description here
insert image description here

insert image description here
insert image description here

Ok, let's summarize the whole process of SpringBoot's automatic loading.

  • First, load the metadata information
  • Get information about classes that need to be autoloaded
    • Determine whether automatic configuration is enabled
    • Get a list of candidate auto-configuration classes
    • Get the list of auto-configuration classes that need to be excluded
    • Check for auto-configuration classes that need to be excluded
    • Remove classes that need to be excluded from the auto-configuration class list
    • Get the configuration class filter to filter the list of candidate automatic configuration classes
    • Trigger an autoconfig import event and return a new autoconfig entry
  • List of registered bean definitions

Guess you like

Origin blog.csdn.net/weixin_47533244/article/details/130763568