参看:
- 博客1:https://blog.youkuaiyun.com/u014745069/article/details/83820511
- 博客2:https://afoo.me/posts/2015-07-09-how-spring-boot-works.html
- SpringBoot文档:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html
文章目录
零、前言
SpringBoot基于Spring4提供的 按条件配置Bean 的能力使得SpringBoot没有了繁琐的配置。这些优点就使得我们 新建一个SpringBoot项目 变得及其的简单。
在SpringBoot中的配置文件如.properties
和.yml
是不可或缺的,而在SpringBoot项目中,没有配置什么扫描或者是加载配置文件等,那么SpringBoot是如何使得我们的配置文件生效的?往下看。
SpringBoot自动装配,简而言之,原理就是:
Spring Boot启动后,在 @EnableAutoConfiguration注解的作用下,启动器会找所有的External Libraries中的META-INF/spring.factories配置文件(都是以为键值对存储)中的所有自动配置类,并对其进行加载。而这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类。自动配置类能通过以Properties结尾命名的类,取得在全局配置文件中配置的属性,如:server.port
(key-value形式)。而XxxxProperties类是通过 @ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。
JavaConfig:就是SpringBoot项目启动类中main方法里 SpringApplication.run()传递进去的类,比如
@SpringBootApplication public class HelloSpringBoot { public static void main(String[] args) throws Exception { SpringApplication.run(HelloSpringBoot.class, args); } }
中的HelloSpringBoot就是一个JavaConfig,而SpringApplication.run就会开始加载必要的bean。
SpringBoot自动配置流程图
下面就是一些分析。
一、SpringBoot启动类注解
查看官方文档并没有发现自动配置的原理,但是我们知道SpringBoot必须有一个启动类,而启动类的@SpringBootApplication注解必不可少。
@SpringBootApplication
public class xxxApplication {
public static void main(String[] args) {
SpringApplication.run(xxxApplication.class, args);
}
}
下面就来看一看@SpringBootApplication到底怎样。
@SpringBootApplication
查看@SpringBootApplication源码,可以看出它是一个复合注解
@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三个非常重要的注解。那么要明白@SpringBootApplication注解的作用,当然就得先明白以上那三个注解的作用了,一个一个来分析。
@SpringBootConfiguration
查看源码,顺便把注释Download下来,看一下注解:
注释的大致意思就是:在这个注解上面(@SpirngBootConfiguration),又有一个 @Configuration 注解。@SpirngBootConfiguration的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了 @Configuration 的类,并且读取其中的配置信息。
@EnableAutoConfiguration
还是一样,查看源码:
这里的注解太多,大致就是说一些自动配置时需要开发者注意的点。而当你去阅读官方文档的时候,就会阅读到下面这一段话:
The second class-level annotation is @EnableAutoConfiguration . This annotation tells Spring Boot to “guess” how you want to configure Spring, based on the jar dependencies that you have added. Since spring-boot-starter-web added Tomcat and Spring MVC, the auto-configuration assumes that you are developing a web application and sets up Spring accordingly.
大致意思是:第二级的注解 @EnableAutoConfiguration ,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置 Spring。比如我们引入了 spring-boot-starter-web ,而这个启动器中帮我们添加了 tomcat 、 SpringMVC 的 依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
简单点说就是:SpringBoot内部对大量的第三方库进行了默认配置,我们引入对应库所需的依赖,那么默认配置就会生效。
而其中的@EnableAutoConfiguration实现的关键功能由@Import提供的,我们查看AutoConfigurationImportSelector类的源码就不看了,它的作用就是扫描所有导入依赖的具有META-INF/spring.factories的jar包。如spring-boot-autoconfigure-x.x.x.x.jar里就有一个这样的spring.factories文件。里面所有的配置文件都是键值对(key-value),可以去查看源代码。
之后找到所有的JavaConfig自动配置类的全限定名对应的class,之后实现自动配置类加载到Spring容器中。
@ComponentScan
点开源码,也没有什么特别的,发现这一段注释说明了此注解的作用
大致意思是:配置组件扫描的指令。提供了类似与<context:component-scan>
标签的作用,通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包。
而@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子 包。因此,一般启动类会放在一个比较前的包目录中。
二、自动配置生效
1.依靠注解
通过上面的分析,我们了解到启动类启动后会自动配置三方工具。而每一个XxxxAutoConfiguration自动配置类都是在某些条件之下才会生效的,这些条件的限制在Spring Boot中以注解的形式体现,常见的条件注解有如下几项:
- @ConditionalOnBean:当容器里有指定的bean的条件下生效。
- @ConditionalOnMissingBean:当容器里不存在指定bean的条件下生效。
- @ConditionalOnClass:当类路径下有指定类的条件下生效。
- @ConditionalOnMissingClass:当类路径下不存在指定类的条件下生效。
- @ConditionalOnProperty:指定的属性是否有指定的值,比如@ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。
以大家都很熟悉的SpringMVC为例,查看mvc自动配置类WebMvcAutoConfiguration。
@Configuration:声明这个类是一个配置类。
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }):判断是否引入了相 关依赖,引入依赖后该条件成立,当前类的配置才会生效。
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class):WebMVCConfigurationSupport类配置后,那么这个默认配置就会失效。
当然还有其他的配置文件中 xxxAutoConfiguration 可能又会有各自的不同。
2.自动配置生效流程图
先看图,再看解释:
图片参考:https://afoo.me/posts/2015-07-09-how-spring-boot-works.html
SpringApplication作为一个Bootstrap(是Tomcat中的)类,可以加载JavaConfig形式的配置, 也可以加载XML形式的配置。之后以JavaConfig为主线,SpringBoot会创建一个对应处理JavaConfig形式配置的AnnotationConfigApplicationContext实例(或者有Servlet等类,则创建ConfigurableWebApplicationContext)。
在ApplicationContext创建的之前和之后, SpringBoot会使用SpringFactoriesLoader这个特性,从当前classpath下所有的META-INF/spring.factories下加载如下类型的一些callback接口并在前中后等不同时机执行:
- org.springframework.boot.SpringApplicationRunListener
- org.springframework.context.ApplicationContextInitializer
- org.springframework.context.ApplicationListener
ApplicationContext就正式加载SpringApplication.run方法传入进来的配置了(JavaConfig形式或者XML形式)。
因为标注了@SpringBootApplication,容器会自动完成指定语义的一系列职能,包括@EnableAutoConfiguration要求的事情。
之后的CommandLineRunner是用来扩展的,根据需求和场景,实现一些自己的CommandLineRunner并添加到容器来对SpringBoot应用进行某种扩展。
三、结语
一定要记得:
XxxxProperties类的含义是:封装配置文件中相关属性。
XxxxAutoConfiguration类的含义是:自动配置类,目的是给容器中添加组件。
而其他的主方法启动,则是为了加载这些五花八门的XxxxAutoConfiguration类。