• 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,回答了这些就够了。

  • 相关阅读:
    物联网、云计算、软件设计的前景都怎么样啊有没有业内懂哥
    【线性代数】P2 行列式的性质
    linux安装mysql 8.0.20
    Python-日志模块
    9. 内核、文件系统加载工具
    1.用递归求一个正整数的逆序数
    C语言实现调用python绘图
    LeetCode46全排列(回溯入门)
    Android12之/proc/pid/status参数含义(一百六十五)
    金蝶云星空与旺店通·旗舰奇门对接集成收料通知单查询连通新增采购订单(金蝶收料通知单-旺店通采购订单开单)
  • 原文地址:https://blog.csdn.net/m0_66201040/article/details/127454032