谈谈Spring Boot自动装配

91 阅读5分钟

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 + 鼠标左键点击进入,查看源码👇:

image-20230103204642722

​ 图1 - @SpringBootApplication部分源码

这里重点的注解有3个:

  • @SpringBootConfiguration

  • @EnableAutoConfiguration

  • @ComponentScan


@SpringBootConfiguration(源码👇)

image-20230103205731799

​ 图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 的自动配置类:

image-20230103213122314

image-20230103213206136

image-20230103213234745

image-20230103212524152

​ 图3 - External Libraries目录

如果找不到这个位置,可以使用快捷键双击Shift->输入WebMvcAutoConfiguration即可

打开WebMvcAutoConfiguration源码👇:

image-20230103213633726

​ 图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该类中定义了什么:

视图解析器:

image-20230103214122471

​ 图5 - WebMvcAutoConfiguration部分源码

WebMvcAutoConfiguration中使用了@AutoConfigureAfter注解, 意为指定的类加载完了后,再加载本类

@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
      ValidationAutoConfiguration.class })

以上👆代码段可在图4 - WebMvcAutoConfiguration源码中找到,

下面的👇DispatcherServletAutoConfiguration也可在该位置找到


DispatcherServletAutoConfiguration中又做了很多事情, 比如配置了前端控制器

image-20230103215404183

​ 图6 - DispatcherServletAutoConfiguration部分源码

总结

  1. @SpringBootApplication注解内部是3大注解功能的集成

    • @ComponentScan: 开启组件扫描
    • @SpringBootConfiguration: 作用等同于@Configuration注解,也是用于标记配置类
    • @EnableAutoConfiguration: 内部导入AutoConfigurationImportSelector,该类中有个getCandidateConfigurations方法, 读取jar包中META-INF/spring.factories文件中配置类, 再根据条件进行加载和配置, 比如: AOP / PropertyPlaceholder / FreeMarker /HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager /DispatcherServlet / WebMvc 等等
  2. SpringApplication.run(..)的作用

    • 启动SpringBoot应用
    • 加载自定义的配置类,完成自动配置功能
    • 把当前项目配置到嵌入的Tomcat服务器
    • 启动嵌入的Tomcat服务器

简单来说Springboot 的自动装配原理:

在 SpringBoot 的@SpringBootApplication 注解中有一个注解@EnableAutoConfiguration ,这个注解的功能就是实现自动装配的。他的作用主要是扫描导入每个 jar 中的 spring.factory 中的内容,然后把里面的内容读取到内存中,其实就是读取一堆的配置类。然后引入之后里面有些@Codictional 的注解,根据特定的条件帮我们创建 bean 并注入,省去我们自己配置 bean 的过程,简化了开发步骤