SpringBoot 学习之自动配置基本原理(八)

Spring 源码系列

1、Spring 学习之扩展点总结之后置处理器(一)
2、Spring 学习之扩展点总结之后置处理器(二)
3、Spring 学习之扩展点总结之自定义事件(三)
4、Spring 学习之扩展点总结之内置事件(四)
5、Spring 学习之扩展点总结之@Import(五)
6、Spring 学习之AOP总结之基础介绍(六)
7、Spring 学习之AOP总结之实现代理(七)
8、SpringBoot 学习之自动配置基本原理(八)
9、SpringBoot 学习之启动原理(九)
10、ElasticSearch学习随笔之SpringBoot Starter 操作
11、图数据库 Neo4j 学习之SpringBoot整合
12、SpringBoot 学习之常用 Filter / Advice 总结
13、SpringBoot+FastJson 优雅的过滤 Response Body
14、Spring Security + Oauth2 认证授权

前言

Spring boot框架,是一个使用起来特别方便的框架,基本上三步走就可以构建起来一个应用了(第一步:pom.xml 引入依赖,第二步:配置 yml 或者 properties 配置文件, 第三部:main方法调用 run() 方法),如此方便都是基于框架的注解来实现,而且基本上所有的功能都可以通过注解来实现,避免了我们再去配置复杂的 xml 文件了。
接下来了解一下Spring Boot框架的几个核心的注解。

1、@SpringBootApplication

这个配置是配置在我们的启动类上的,通过这个配置类我们就可以启动我们的Boot应用了,那么这个配置类的原理是什么呢?

@SpringBootApplication
public class SpringInitializeApp {

    public static void main(String[] args) {
        SpringApplication.run(SpringInitializeApp.class, args);
    }
}

下面是 @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) })
public @interface SpringBootApplication {...
}

可以看到这个注解中包含了好多注解,首先前四个注解(@Target、@Retention、@Documented、@Inherited)则是JDK的元注解,元注解在《元注解了解》中有所讲解,紧接着下面就是两个特别重要的注解(@SpringBootConfiguration、@EnableAutoConfiguration),见下面讲解。

2、@SpringBootConfiguration

见名知意,它就是SpringBoot的一个配置类,此注解标记在某个类上,这个类就是SpringBoot的一个配置类,下面是它的注释。

Indicates that a class provides Spring Boot application @Configuration. Can be used as an alternative to the Spring’s standard @Configuration annotation so that configuration can be found automatically (for example in tests).
Application should only ever include one @SpringBootConfiguration and most idiomatic Spring Boot applications will inherit it from @SpringBootApplication.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
}

从@SpringBootConfiguration源码注释中说,声明了一个类提供Spring Boot应用的@Configuration,用于一个独有的Spring的@Configuration并且应用只能有一个@SpringBootConfiguration注解,也将会继承@SpringBootApplication注解。

3、@EnableAutoConfiguration

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

在这个注解中,除了四个元注解,还有两个注解,@AutoConfigurationPackage@Import 注解。

那最重要的就是这个 @Import了,@Import注解是 Spring 提供的,可以参考《Spring 学习之扩展点总结之@Import(五)》 对 @Import 扩展点的讲解。
可以看到 @Import 引入了一个 AutoConfigurationImportSelector.class 配置类,这个配置类实现了 DeferredImportSelector 接口,在 《Spring学习之扩展点总结之@Import》篇中提到,DeferredImportSelector 接口继承了 ImportSelector 接口,和 ImportSelector 的不同点就是,DeferredImportSelector 是延迟执行的。
那么在配置类实现了DeferredImportSelector接口后,用 @Import 导入时则会调用 selectImports() 方法,selectImports() 方法则调用了 getAutoConfigurationEntry() 方法,接下来看看源码(重要的源码加了注释)。

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

	略去中间不重要的代码...

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		//这里调了 getAutoConfigurationEntry
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
		// 从META-INF/spring.factories中获得候选的自动配置类
		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
		//去重操作
		configurations = removeDuplicates(configurations);
		//根据 EnableAutoConfiguration 注解中的 exclude 和 excludeName 获取到不需要自动装配的类列表
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		//进行排除操作,根据 @EnableAutoConfiguration.exclude、@EnableAutoConfiguration.excludeName、spring.autoconfigure.exclude 这三个配置
		checkExcludedClasses(configurations, exclusions);
		//排除 exclusions
		configurations.removeAll(exclusions);
		//通过读取sprin.factories 中的OnBeanCondition\OnClassCondition\OnWebApplicationCondition进行过滤
		configurations = getConfigurationClassFilter().filter(configurations);
		//这个方法调用了 AutoConfigurationImportListener Bean,分别把候选的配置列表和排除列表传进去进行扩展
		//AutoConfigurationImportListener 继承了Spring 的事件监听 EventListener,利用事件监听来实现自动配置
		fireAutoConfigurationImportEvents(configurations, exclusions);
		return new AutoConfigurationEntry(configurations, exclusions);
	}

关于 Spring 的 EventListener,可前往 《Spring 学习之扩展点总结之内置事件(三)》 了解。

4、@AutoConfigurationPackage

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}

@AutoConfigurationPackage 的作用则是将当前配置类的所在的包保存在 BasePackages 的 Bean 中,供 Spring 内部使用,看此注解源码,用 @Import 注解引入了一个注册类 AutoConfigurationPackages.Registrar.class就是注册了一个保存当前配置类所在包的一个Bean

5、自动装配总结

所有的 SpringBoot 应用,都会引入一个 spring-boot-autoconfigure 的包(如下图),这个包中就有 SpringBoot自动装配需要初始化的所有配置文件 spring.factories,此配置文件是以 key=value 的形式来配置的,value 多值时用逗号( , ) 隔开, 该文件中定义了对于初始化和监听器等信息,真正完成自动配置任务的是 org.springframework.boot.autoconfigure.EnableAutoConfiguration 注解。
spring.factories 里面定义了大量的配置,又有很多SpringBoot整合的 spring-boot-starter-*** 的包,官网则提供了所有的配置类表

spring-boot-autoconfigure.jar

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值