SpringBoot 源码系列-自动配置及 starter 机制解析
一家之言,如有任何错误,请批评指出,不胜感激
本篇主要来讨论研究两个问题:1、什么自动配置,2、如何编写自动配置
在使用 Spring
作为项目开发框架的过程中,当需要集成某个组件时,通常需要大量的 xml
配置才可以让项目工程 run
起来,下面先以 mybatis
为例,来看下如何使用 mybatis-Spring
模块,需要哪些必不可少的依赖和配置。
使用 mybatis-spring
任何组件的集成都绕不过两个问题:依赖和配置,关于配置在这篇文章中介绍了配置的一些点,有兴趣的可以看下。
依赖
从 mybatis
的官方文当可以了解到,要使用 MyBatis-Spring
模块,需要在类路径下包含 mybatis-spring.jar
文件和相关依赖(如:mysql-connector-java
)即可。如果使用 Maven
作为构建工具,则在 pom.xml
中加入以下代码即可:
1 | <dependency> |
bean 配置
Spirng
集成 mybatis
通常需要以下 bean
配置:
1.dataSource
1 | <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" |
2.sqlSessionFactory
1 | <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> |
3.其他:包扫描和事务配置
1 | <!-- DAO 接口所在包名,Spring 会自动查找其下的类,并将其定义为一个 Spring Bean --> |
这些个 bean 是在 Spring 中使用 mybatis 框架时基本必不可少的配置。那么在 SpringBoot 中呢?
SpringBoot 中如何集成 mybatis 的
SpringBoot 集成 mybatis 非常简单,加一下下面的 starter ,再在 application.properties 配置下数据库连接配置即可;不需要配置 datasource,sqlSessionFactory 等这些 bean。
1 | <dependency> |
官方文档:https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
mybatis starter 是如何规避 bean 配置的
引用 mybatis-spring-boot-starter
既然可以不用在 xml
中配置 bean
,那肯定是这些 bean
是在 mybatis-spring-boot-starter
中通过某种方式被创建了。
在 SpringBoot
官方文档的描述中,starter
只是用来管理依赖的,一般不会有代码,自动配置的代码一般在 xxxx-autoconfigure
中。mybatis
的自动配置相关代码是在 mybatis-spring-boot-autoconfigure
中。
mybatis-spring-boot-autoconfigure
这依赖中只有简单的几个类,其中最核心的就是 MybatisAutoConfiguration
这个配置类。另外一个 MybatisProperties
是 mybatis spring boot
的属性配置类,就是常见的 mybatis.xxxx
。
MybatisAutoConfiguration 自动配置类
MybatisAutoConfiguration
的定义及其生效条件:
- 1.当前
classpath
下必须有SqlSessionFactory
和SqlSessionFactoryBean
这两个类 - 2.存在
DataSource bean
实例 - 3.有配置类
MybatisProperties
实例 - 4.在
DataSourceAutoConfiguration
和MybatisLanguageDriverAutoConfiguration
两个自动配置类之后刷新
1 |
|
从上面的代码片段大体可以知道 MybatisAutoConfiguration
所做的事情主要包括以下几点:
- 1、刷新
SqlSessionFactory
和SqlSessionFactoryBean
两个bean;
- 2、
afterPropertiesSet
中做一些准备或者检验工作(这里就是check 了 mybatis
的配置文件是否配置了)
关于 DataSource
的 bean
,则是由 DataSourceAutoConfiguration
这个配置类中来定义。
具体代码有兴趣的读者可以自己查阅相关源码,这里就不展开了。
所以整体看来, MybatisAutoConfiguration
及其所依赖的 xxxConfiguration
会帮助用户定义 bean
和解析配置。
mybatis 自动配置的 bean 是如何生效的
上面分析到 MybatisAutoConfiguration
及其依赖的配置自动类会帮助创建运行时所需要的 bean
,那么这些 bean
是如何被 SpringBoot
框架感知并加载的呢?
其实一般的项目工程中,如果我们在一个类上打了 @Configuration
注解的话,Spring
会直接能够加载到的(前提是这个类所在的包在启动类的子包下)。但是在框架层面,项目的包和所引入的组件包的包路径肯定是有差异的,所以在一些情况下会刷不到依赖中的 bean
。
SpringBoot
中提供了一种类似于 SPI
机制的方式来帮忙加载 EnableAutoConfiguration、ApplicationListner、ApplicationContextInitializer
等类型的 bean
。比如 mybatis
自动配置的配置如下:
1 | # Auto Configure |
其处理逻辑在 SpringApplication
类中,具体解析方法如下:
1 | private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, |
如何编写自己的 starter
本小节将结合上面的描述,自定义一个 starter
,让你的项目和 xml bean
配置说再见。
场景描述:有两个 bean
,一个 parentBean
,一个 childBean
,parentBean
需要依赖 childBean
,parentBean
中又要依赖 http
包
原来的 xml
配置:
1 | <bean id="parentBean" class="com.glmapper.bridge.boot.service.impl.ParentBean"> |
下面考虑的是将这些 bean
作为公共组件提供给其他项目工程用,从框架角度来看,最佳实践是:
- 提供一个
autoconfigure
模块用于编写自动配置类代码 - 提供一个
starter
,用于提供给外部用户使用
编写 autoconfigure
自动配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// parentBean 依赖 HttpClient,所以如果没有 HttpClient 则不会刷新当前自动配置类
public class GlmpperAutoConfiguration {
// ParentBean bean 定义
// 如果当前 Spring 容器中已经存在 parentBean则不会再创建
public ParentBean parentBean(){
return new ParentBean();
}
// ChildBean bean 定义
public ChildBean childBean(){
return new ChildBean();
}
}依赖 scope 使用 provided,不直接打在 autoconfigure 依赖中
1
2
3
4
5
6
7
8<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
<scope>provided</scope>
</dependency>
</dependencies>编写 spring.factories,在 resources/META-INF/ 新建一个 spring.factories 文件,配置如下:
1
2
3# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.glmapper.bridge.boot.autoconfigure.GlmpperAutoConfiguration
编写 starter
starter 里面没有代码,只做依赖管控
1 | <dependency> |
starter
里面包括了自动配置的依赖和 httpclient
的依赖,所以用户在引入 starter
之后所有生效条件都满足了,就会在启动时直接刷新。
示例工程: https://github.com/glmapper/springboot-series-guides.git(`guides-autoconfigure` 模块和
guides-starter
模块)
小结
本篇以 mybatis
为例,对 spring
环境和 SpringBoot
环境下的使用方式做了简单对比;以此为切入点,介绍了 SpringBoot
中的自动配置及 starter
最佳实践。
SpringBoot 源码系列-自动配置及 starter 机制解析
http://www.glmapper.com/2020/01/05/springboot/springboot-series-auto-configure/