【Spring Boot】Spring Boot 自动配置原理 图文并茂

在这里插入图片描述

为了方便测试,自定义了一个SprongBootStarter

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sgg.aopcache.cache.conf.RedissonAotoConfiguration

image-20220317225154599

1.@SpringBootApplication 核心注解

注解的元信息

@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) })

看这个注解 @EnableAutoConfiguration 看名字就知道 开启自动配置

好,点进去这个注解

2. @EnableAutoConfiguration 开启自动配置注解

首先看下这个注解的元信息和属性

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	/**
	 * Environment property that can be used to override when auto-configuration is
	 * enabled.
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

exclude() excludeName() 如果需要排除某些自动配置类 可以给这两个参数设置值

最重要的看这个注解

3.@Import(AutoConfigurationImportSelector.class)

@Import注解将某个组件导入spring容器中

我们看下 AutoConfigurationImportSelector 这个类都干了什么事情

找到这个方法 selectImports

image-20220317225721914

调用了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);
	}

image-20220317230607646

image-20220317230836792

getBeanClassLoader()

可以看到这个方法的第二个参数获取了类加载器 想想我们自定义starter 的META-INF 文件夹是放在哪里的?

放在resource目录下,这个目录的路径由谁加载,由 AppClassLoader负责加载

image-20220317231037261

点进loadFactoryNames 方法

4. SpringFactoriesLoader.loadFactoryNames

image-20220317231256193

获取了 @EnableAutoConfiguration 注解的全限定类名

image-20220317231412045

image-20220317231505077

首先执行这个方法 loadSpringFactories(classLoader) 注意把类加载器传进去了

这个方法返回一个 Map<String, List>

然后再调用它的 .getOrDefault(factoryTypeName, Collections.emptyList()) 方法 也就是获取key = factoryTypeName 的value

而value 是一个String类型的集合 也就是自动配置类的全限定类名

我们跟进这个方法看一下

5.loadSpringFactories(classLoader)

image-20220317231832929

image-20220317231939973

重点看这个else代码块都做了什么事

 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] var9 = 		StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryImplementationName = var9[var11];
                            result.add(factoryTypeName, factoryImplementationName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;

image-20220317222416956

image-20220317222952699

如果是我们自定义的 spring.factories 配置文件,我们一般只会写 org.springframework.boot.autoconfigure.EnableAutoConfiguration= xxxx

而springboot官方的starter不单单只有

org.springframework.boot.autoconfigure.EnableAutoConfiguration

image-20220317232301134

所以在这我们打断点多循环几次

idea64_Cyg5Ar5RcZ

image-20220317223728838

image-20220317232421615

最后可以看到 我们自定义starter 的 spring.factories文件信息已经被放到了 LinkedMultiValueMap result 中 并返回

返回前还将数据都放到了缓存中

image-20220317232601396

至此,候选的自动配置类全限定类名都已经拿到了,之后还要经历筛选和过滤

image-20220317233327997

最终返回经过了排除和过滤的自动配置类的全限定名数组

在这里插入图片描述

评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋日的晚霞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值