SoringBoot自动装配原理

简单总结

SpringBoot自动配置主要是通过@EnableAutoConfiguation,@Conditional,@EnableConfigProperties,@ConfigurationProperties等注解实现的。
具体流程如下:当我们写好一个启动类后,我们会在启动类上加一个@SpringBootApplication,我们可以点开这个注解可以看到它内部有一个@EnableAutoConfiguation的注解,我们继续进入这个注解可以看到一个@Import的注解,这个注解引入了一个AutoConfigurationImportSelector的类。我们继续打开这个类可以看到它有一个selectorImport的方法,这个方法又调用了一个getCandidateConfigurations方法,这个方法内部通过SpringFactoriesLoader.loadFactoryNames最终调用loadSpringFactories加载到一个META-INF下的spring.factories文件。打开这个文件可以看到是一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔。当我们通过springApplication.run启动的时候内部就会执行selectImports方法从而找到配置类对应的class。然后将所有自动配置类加载到Spring容器中,进而实现自动配置。

Spring Boot 自动配置原理

使用 Spring Boot 之后,做一个整合了 Spring MVC 的 Web 工程开发,变的无比简单,那些繁杂的配置都消失不见了,这是如何做到的?一切魔力的开始,都是从我们的 main 函数来的,所以我们再次来看下启动类:

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

从上面代码我们发现特别的地方有两个:

  • 注解:@SpringBootApplication
  • run方法:SpringApplication.run()。

1、了解 @SpringBootApplication

点击进入,查看源码:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JbjobdU7-1640315963654)(图/1525488226710.png)]

这里重点的注解有3个:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

1.1、@SpringBootConfiguration

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFriLKNG-1640315963656)(图/1525488518514.png)]

通过这段我们可以看出,在这个注解上面,又有一个 @Configuration 注解。通过上面的注释阅读我们知道:这个注解的作用就是声明当前类是一个配置类,然后 Spring 会自动扫描到添加了 @Configuration 的类,并且读取其中的配置信息。而 @SpringBootConfiguration 是来声明当前类是 Spring Boot 应用的配置类,项目中只能有一个。所以一般我们无需自己添加。

1.2、@ComponentScan

我们的 @SpringBootApplication 注解声明的类就是 main 函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。

1.3、@EnableAutoConfiguration

@EnableAutoConfiguration 的作用,告诉 Spring Boot 基于你所添加的依赖,去“猜测”你想要如何配置 Spring。比如我们引入了 spring-boot-starter-web,而这个启动器中帮我们添加了 tomcatSpringMVC 的依赖。此时自动配置就知道你是要开发一个 Web 应用,所以就帮你完成了 Web 及 Spring MVC 的默认配置了!

Spring Boot 内部对大量的第三方库或 Spring 内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有,那么默认配置就会生效。那么带来新的问题,如下:

  • 这些默认配置是在哪里定义的呢?
  • 为何依赖引入就会触发配置呢?

2、如何自动配置

@EnableAutoConfiguration 注解中导入了一个 AutoConfigurationImportSelector 配置类,该类中有个 getCandidateConfigurations 方法,方法的作用是委托 SpringFactoriesLoader 去读取 jar 包中的 META-INF/spring.factories 文件,并加载里面配置的自动配置对象,包括:AOP,PropertyPlaceholder,FreeMarker,HttpMessageConverter,Jackson,DataSourceDataSourceTransactionManager,DispatcherServlet 等等。

其实在我们的项目中,已经自动引入了一个依赖:spring-boot-autoconfigure,上面说到的这些自动配置类,都来自该包。

虽然 spring.factories 文件中定义了很多配置类,但并不是所有配置类都会生效,只有符合条件的是才会自动装配。

我们来看一个我们熟悉的,例如 Spring MVC,查看其自动配置类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HhYyv44U-1640315963656)(图/1525499859426.png)]

打开 WebMvcAutoConfiguration:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ohB28xb-1640315963657)(图/1525500000816.png)]

我们看到这个类上的 4 个注解:

  • @Configuration:声明这个类是一个配置类

  • @ConditionalOnWebApplication(type = Type.SERVLET)

ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是 Type.SERVLET 类型,我们现在的项目就满足了,就是一个 Web 工程。

  • @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

这里的条件是 OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer。这里就是判断你是否引入了 Spring MVC相关依赖,引入依赖后该条件成立,当前类的配置才会生效!

  • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

这个条件与上面不同,OnMissingBean,是说环境中没有指定的 bean 这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个 WebMVCConfigurationSupport 的 bean,代表容器里已经存在该 bean 了,那么这个默认配置就会失效!

接着,我们查看 WebMvcAutoConfiguration 该类中定义了什么:

视图解析器:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuqnurYU-1640315963658)(图/1525500405278.png)]

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

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

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

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
    dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
    dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
    dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
    return dispatcherServlet;
}

3、总结

  • @SpringBootApplication 注解内部是3大注解功能的集成
    • @ComponentScan:开启组件扫描
    • @SpringBootConfiguration:作用等同于 @Configuration 注解,也是用于标记配置类
    • @EnableAutoConfiguration:内部导入 AutoConfigurationImportSelector,该类中有个 getCandidateConfigurations 方法,读取 jar 包中 META-INF/spring.factories 文件中配置类,再根据条件进行加载和配置,比如:AOP,PropertyPlaceholder,FreeMarker,HttpMessageConverter,Jackson,DataSourceDataSourceTransactionManager,DispatcherServlet,WebMvc 等等
  • SpringApplication.run(…)的作用
    • 启动 Spring Boot 应用
    • 加载自定义的配置类,完成自动配置功能
    • 把当前项目配置到嵌入的 Tomcat 服务器
    • 启动嵌入的 Tomcat 服务器
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值