Spring Boot自动装配
使用SpringBoot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失
不见了,这是如何做到的?
一切魔力的开始,都是从我们的main函数来的,所以我们再次来看下启动类:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
我们发现特别的地方有两个:
-
注解:@SpringBootApplication
-
run方法:SpringApplication.run()
我们分别来研究这两个部分。
了解@SpringBootApplication
Ctrl + 鼠标左键点击进入,查看源码👇:
图1 - @SpringBootApplication部分源码
这里重点的注解有3个:
-
@SpringBootConfiguration -
@EnableAutoConfiguration -
@ComponentScan
@SpringBootConfiguration(源码👇)
图2 - @SpringBootConfiguration源码
通过这段我们可以看出,在这个注解上面,又有一个 @Configuration 注解。
翻译以上注释:
指示类提供Spring Boot应用程序@Configuration。可以用作Spring的标准@Configuration注释的替代,以便可以自动找到配置(例如在测试中)。 应用程序应该只包含一个@SpringBootConfiguration,大多数惯用的Spring Boot应用程序都会从@SpringBootApplication继承它。
自: 1.4.0
作者: 菲利普·韦伯
通过阅读上面的注释我们知道:
这个注解的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了@Configuration 的类,并且读取其中的配置信息。而 @SpringBootConfiguration 是来声明当前类是SpringBoot应用的配置类,项目中只能有一个。所以一般我们无需自己添加。
@ComponentScan
我们的@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。
@EnableAutoConfiguration
@EnableAutoConfiguration 的作用,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置Spring。比如我们引入了 spring-boot-starter-web ,而这个启动器中帮我们添加了 tomcat 、SpringMVC 的依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
SpringBoot内部对大量的第三方库或Spring内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么默认配置就会生效。
那么
-
这些默认配置是在哪里定义的呢?
-
为何依赖引入就会触发配置呢?
@EnableAutoConfiguration注解中导入了一个AutoConfigurationImportSelector配置类,该类中有个getCandidateConfigurations方法,方法的作用是委托SpringFactoriesLoader去读取jar包中的METAINF/spring.factories文件, 并加载里面配置的自动配置对象,包括: AOP / PropertyPlaceholder /FreeMarker / HttpMessageConverter / Jackson / DataSource /DataSourceTransactionManager /DispatcherServlet / WebMvc 等等。
其实在我们的项目中,已经自动引入了一个依赖:spring-boot-autoconfigure,上面说到的这些自动配置类, 都来自该包。
虽然spring.factories文件中定义了很多配置类, 但并不是所有配置类都会生效, 只有符合条件的是才会自动装配。
我们来看一个我们熟悉的,例如SpringMVC,查看mvc 的自动配置类:
图3 - External Libraries目录
如果找不到这个位置,可以使用快捷键双击Shift->输入WebMvcAutoConfiguration即可
打开WebMvcAutoConfiguration源码👇:
图4 - WebMvcAutoConfiguration部分源码
我们看到这个类上的4个注解:
-
@Configuration:声明这个类是一个配置类 -
@ConditionalOnWebApplication(type = Type.SERVLET)ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是Type.SERVLET类型,我们现在的项目就满足了, 就是一个web工程
-
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurer.class })这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer。这里就是判断你是否引入了SpringMVC相关依赖,引入依赖后该条件成立,当前类的配置才会生效!
-
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的bean, 代表容器里已经存在该bean了,那么这个默认配置就会失效!
接着,我们查看WebMvcAutoConfiguration该类中定义了什么:
视图解析器:
图5 - WebMvcAutoConfiguration部分源码
WebMvcAutoConfiguration中使用了@AutoConfigureAfter注解, 意为指定的类加载完了后,再加载本类
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
以上👆代码段可在
图4 - WebMvcAutoConfiguration源码中找到,下面的👇
DispatcherServletAutoConfiguration也可在该位置找到
而DispatcherServletAutoConfiguration中又做了很多事情, 比如配置了前端控制器
图6 - DispatcherServletAutoConfiguration部分源码
总结
-
@SpringBootApplication注解内部是3大注解功能的集成
@ComponentScan:开启组件扫描@SpringBootConfiguration:作用等同于@Configuration注解,也是用于标记配置类@EnableAutoConfiguration:内部导入AutoConfigurationImportSelector,该类中有个getCandidateConfigurations方法, 读取jar包中META-INF/spring.factories文件中配置类, 再根据条件进行加载和配置, 比如: AOP / PropertyPlaceholder / FreeMarker /HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager /DispatcherServlet / WebMvc 等等
-
SpringApplication.run(..)的作用
- 启动SpringBoot应用
- 加载自定义的配置类,完成自动配置功能
- 把当前项目配置到嵌入的Tomcat服务器
- 启动嵌入的Tomcat服务器
简单来说Springboot 的自动装配原理:
在 SpringBoot 的@SpringBootApplication 注解中有一个注解@EnableAutoConfiguration ,这个注解的功能就是实现自动装配的。他的作用主要是扫描导入每个 jar 中的 spring.factory 中的内容,然后把里面的内容读取到内存中,其实就是读取一堆的配置类。然后引入之后里面有些@Codictional 的注解,根据特定的条件帮我们创建 bean 并注入,省去我们自己配置 bean 的过程,简化了开发步骤