Spring Cloud Alibaba reading notes_2: Spring Boot automatic assembly

Spring Boot automatic assembly

Simply put, it is the process of assembling the Bean into the IoC container.

Realization of automatic assembly

  • Automatic assembly in Spring Boot is enabled through the @EnableAutoConfiguration annotation, which is declared in the startup class annotation @SpringBootApplication .
@SpringBootApplication
public class Application {
    
    
	public static void main(String[] args) {
    
    
		SpringApplication.run(Application.class, args);
	}	
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    
     @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    
    }

EnableAutoConfiguration

  • Enter the @EnableAutoConfiguration annotation, you can see the @Import annotation (import an AutoConfigurationImportSelector class to realize the import of the configuration class), @AutoConfigurationPackage annotation (function: scan all components under the package and subpackages of the class where the annotation is located to Spring IoC container)
    • AutoConfigurationImportSelector: AutoConfigurationImportSelector implements the DeferredImportSelector interface, and the DeferredImportSelector interface inherits from ImportSelector . In ImportSelector , there is only one abstract method: selectImports , which returns a String[ ] . In this array, you can specify the class that needs to be assembled into the IoC container. After importing an implementation class in @Import, the Class name returned in the implementation class will be loaded into the IoC container.
      Insert picture description here
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    
    }
public interface DeferredImportSelector extends ImportSelector {
    
    }
public interface ImportSelector {
    
    
    String[] selectImports(AnnotationMetadata var1);
}

The difference with @Configuration is: ImportSelector can realize batch assembly and selective assembly through logic processing .

Analysis of automatic assembly principle

The core of automatic assembly is to scan the files in the agreed directory for analysis, and after the analysis is complete, import the obtained Configuration configuration class through @ImportSelector to complete the automatic assembly process of Bean. When the project is started, the related operations of automatic assembly will be carried out through the process method of AutoConfigurationImportSelector. The essence is to call the getAutoConfigurationEntry method to obtain all the configuration classes that need to be automatically assembled.
Actual operation: start a SpringBoot project, enter the AutoConfigurationImportSelector, break points in all calls to the getAutoConfigurationEntry method, and run the start main method.

  • selectImports (executed only in the scenario of selective batch configuration)
  • getAutoConfigurationEntry (execute)
  • process (execution)

Focus on the getAutoConfigurationEntry method, let’s expand on what this method does!

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
    
    
    if (!isEnabled(annotationMetadata)) {
    
    
        return EMPTY_ENTRY;
    }
    // 获取@EnableAutoConfiguration注解中的属性exclude、excludeName等
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    // 获得所有自动装配的配置类(后续会展开说明)
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    // 去除重复配置项
    configurations = removeDuplicates(configurations);
    // 根据@EnableAutoConfiguration注解中的属性exclude,移除不需要自动装配的配置类
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    // 对于不属于AutoConfiguration的exclude报错
    checkExcludedClasses(configurations, exclusions);
    // 从configurations去除exclusions
    configurations.removeAll(exclusions);
    // 由所有AutoConfigurationImportFilter类的实例再进行一次筛选
    configurations = filter(configurations, autoConfigurationMetadata);
    // 广播事件,把AutoConfigurationImportEvent绑定在所有AutoConfigurationImportListener子类实例上,主要用于声明打印相关配置类内容
    fireAutoConfigurationImportEvents(configurations, exclusions);
    // 返回(configurations, exclusions)组
    return new AutoConfigurationEntry(configurations, exclusions);
}

The key point is: What does the getCandidateConfigurations method do? SpringFactoriesLoader is used here . It is a conventional loading method provided internally, similar to the SPI [Service Discovery Mechanism] in Java , which scans the META-INF/spring.factories of the classpath . File, spring.factories file is stored in KV** form, loadFactoryNames method will get the corresponding Value value according to Key . Here Key is EnableAutoConfiguration , Value is multiple configuration classes, that is , the return value of getCandidateConfigurations .

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;
}

Insert picture description here


To summarize: four steps

  • Realize the import of configuration class through @Import(AutoConfigurationImportSelector.class)
  • AutoConfigurationImportSelector implements the ImportSelector interface, and implements the assembly loading of the configuration class through the getAutoConfigurationEntry method
  • Through Spring's SpringFactoriesLoader mechanism, scan the classpath path and read the configuration classes that need to be automatically assembled from the META-INF/ spring.factories file
  • Filter by conditions, filter and remove , and finally complete the assembly

Conditional assembly

@Conditional , provides automatic assembly conditional constraints, generally used in conjunction with @Configuration and @Bean . Accepts an array of Condition[ ] . Condition is a functional interface that provides a matches method and provides a matching rule. If the rule is satisfied, it can be injected, otherwise, it will not be injected. Provides contextual judgment for Bean loading.

@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    
    

	/**
	 * All {@link Condition Conditions} that must {@linkplain Condition#matches match}
	 * in order for the component to be registered.
	 */
	Class<? extends Condition>[] value();

}
@FunctionalInterface
public interface Condition {
    
    

	/**
	 * Determine if the condition matches.
	 * @param context the condition context
	 * @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
	 * or {@link org.springframework.core.type.MethodMetadata method} being checked
	 * @return {@code true} if the condition matches and the component can be registered,
	 * or {@code false} to veto the annotated component's registration
	 */
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

@Conditional expands the usage form: better provide context judgment for automatic loading, let Spring decide whether to load the configuration class.

annotation meaning
@ConditionOnBean/@ConditionOnMissingBean Load when a Bean exists or does not exist in the container
@ConditionOnClass/@ConditionOnMissingClass Load when the specified class exists or does not exist in the container
@ConditionOnCloudPlatform Load on the designated cloud platform
@ConditionOnExpression Load based on conditional judgment of SqEI expression
@ConditionOnJava Run the specified version of Java for loading
@ConditionOnJndi The specified resource can be loaded after it is loaded through JNDI
@ConditionOnWebApplication/@ConditionOnNotWebApplication Load when it is or is not a web application
@ConditionOnProperty Specify whether the attribute has a corresponding value to load
@ConditionOnResource The bean to be loaded depends on the specified resource to exist in the classpath for loading
@ConditionOnSingleCandidate Load when determining a single candidate for a given Bean

In addition, Spring-Autoconfiguration-Metadata provided in papers condition automatic assembly batch configuration, the configuration of the file format required to meet:

  • The configuration file path and name must be: /META-INF/spring-autoconfigure-metadata.properties
  • The Key configuration format in the configuration file is: the fully qualified path name of the automatic configuration class. Condition=Value

Guess you like

Origin blog.csdn.net/Nerver_77/article/details/108237124