• Spring Boot自动装配原理


    两个注解

      这个是面试热门问题了,如果只回答了spring.factories是不会留下好印象的,只有详细讲解这个过程,才会给面试官留下一个好印象。
      首先是@SpringBootApplication注解包含了@EnableAutoConfiguration注解,如源码(局部):

    @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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

      再看@EnableAutoConfiguration注解,源码:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

      其余的信息可以不看,只需要看这两个就可以了。

    AutoConfigurationImportSelector

      其实读源码,就是一步一步往下跟就行了,这个类的核心在于这个方法:

    @Override
    	public String[] selectImports(AnnotationMetadata annotationMetadata) {
    		if (!isEnabled(annotationMetadata)) {
    			return NO_IMPORTS;
    		}
    		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      下一步就是调用getAutoConfigurationEntry方法,这个方法长这样:

    protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);
    		fireAutoConfigurationImportEvents(configurations, exclusions);
    		return new AutoConfigurationEntry(configurations, exclusions);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

      这里面的核心代码就是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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

      而SpringFactoriesLoader,类似于JavaSE的ServiceLoader,从META-INFO/spring.factories里读取配置,然后加载配置类。为什么是,是在这里配置的:

    public final class SpringFactoriesLoader {
    
    	/**
    	 * The location to look for factories.
    	 * 

    Can be present in multiple JAR files. */ public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    面试技巧

      这么多东西也很难记住,只要说出@SpringBootApplication到@EnableAutoConfiguration,再到AutoConfigurationImportSelector,在这个类里会调用SpringFactoriesLoader,回答了这些就够了。

  • 相关阅读:
    DKD蒸馏复现
    Python函数详解(四)——Python函数参数使用注意事项
    JavaSE---数组的定义与使用
    集合知识点总结
    关于#人工智能#的问题:我想知道他下面这种遇到代码会换行并且会有一段我标红的代码是怎么实现的(语言-javascript)
    C++【STL】【string类的模拟实现】【string类的深浅拷贝】
    架构解析:Dubbo3 应用级服务发现如何应对双 11 百万集群实例
    为什么要做高新?高新技术企业和科技型企业的区别?
    基于MCU_USB的虚拟串口助手实现
    jsPlumb导航器
  • 原文地址:https://blog.csdn.net/m0_66201040/article/details/127454032