SpringBoot系列之starter原理
前言
SpringBoot 除了提供自身的功能外,还为我们提供了众多开箱即用的starter
,比如常用的像
spring-boot-starter-jdbc
、spring-boot-starter-logging
等。我们只要在 pom 文件中引入这些组件的依赖,springboot就会帮我们加载这些组件的 bean 到 IOC 容器中,并且允许我们对组件的一些配置进行定制,可谓是真正的“开箱即用”,这也是 springboot 现在称为行业事实标准的一个重要原因。那这样杀手锏级别的特性是如何实现的呢?本文我们将探讨这个话题。
依赖包什么都没有?
我们以spring-boot-starter-jdbc
2.0.3.RELEASE版本为例,去 maven 中央仓库下载对应的 jar 包,地址:https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc/2.0.3.RELEASE。点击红框内按钮下载 jar 包:
下载完解压,发现 jar 包内没有 class 文件,也没有 pom.xml:
而 spring.provides
在2.1.0之后的版本被去掉了,我们看下MANIFEST.MF
文件:这里面只是一些介绍和环境信息,what?!不符合客观规律啊,没找到任何有价值的东西啊,那引入这个依赖的 jar 包有啥用呢?
再看依赖包
我们点击右边这个按钮,打开所有的 jar 包看一下:
发现还有 source 的 jar 包。source 的 jar 包和普通的 jar 包区别在于 source 中包含 java 源代码,而普通 jar 包中只有 class 文件,这一点在 jar 包大小上也能看出来,source 包是普通 jar 包的四倍左右大小。
我们下载 source 包看一下:
Ohhhhhh!source 包里有 pom 文件,我们打开 pom 文件:
pom 文件中引入了三个与 Jdbc 有关的依赖,到这里我们大致清楚了:starter 依赖只负责引入相关的功能 jar 包,而不会主动的将 bean 注册到 IOC 容器中。
至于为什么普通 jar 包中没有 pom 文件,我猜测与 maven 的打包机制有关,可能是将 class 文件与 pom 文件分别打包,导致普通 jar 包中看不到 pom.xml。这个知识点属于 maven 的范畴了,等研究 maven 的时候再写文章告诉大家(基础真的很重要)。
starter 与自动装配
我们在上文中看到,starter 依赖只会帮我们引入对应功能的 jar 包,而没有主动将 bean 注册到 IOC 容器中(甚至连 class 文件都没有)。那 springboot 是怎么做到“开箱即用”的呢?这就与springboot 的 AutoConfiguration 也就是自动装配有关系了,关于自动装配的内容在我的另一篇博文《SpringBoot系列之启动流程3-自动装配与@SpringBootApplication注解》中有详细介绍。简单来说就是 springboot 在 classpath 下搜索所有 jar 包中的 spring.factories
文件,将其汇总为将要注册进IOC 容器中的 bean 蓝本。
加载完这些蓝本类之后,不是直接注册进 IOC 容器中,因为直接注册的话太多了,光是注册可能就要花很久,况且有些 bean 我这个应用可能根本用不到呢,那我就白花那么长时间启动了。所以springboot还要借助条件装配,看一下是否满足条件,满足的话才会进行相应功能的自动装配,将相应的bean 注册进 IOC 容器,否则忽略该自动装配。
举个实际的例子:AutoConfiguration =\ JdbcTemplateAutoConfiguration
也是自动装配中的一项:
我们找到这个类看一下源码:
这个类上有一些注解,其中@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
标识出:这个配置类只有在有DataSource.class和JdbcTemplate.class这两个 class 文件的时候才生效,而jdbc-starter 的依赖包中,就包含这两个类,所以JdbcTemplateAutoConfiguration
才能自动装配生效!
总结
starter 是 springboot 提供的开箱即用的组件,这些组件本身不提供主动注册 Bean 的功能,而是向应用中引入依赖,后续 springboot 应用启动,触发自动装配的时候,发现starter 引入的相关依赖,就会将对应功能的 bean 装配进 IOC 容器中。