spring-boot-starter 自动配置的理解
spring boot 相比 spring 之所以简化很多就是因为 spring boot 搭建一个项目的时候可以引入多个 starter,这样就可以直接使用不需要过多的各种配置。spring 官方提供了不少 starter,而我们自己也可以自定义 starter,为了能够区分,从命名上进行了规范。官方的 starter 名称为:spring-boot-starter-xxx,而自定义的为 xxx-spring-boot-starter。
spring boot 能够帮助我们简化开发主要就是基于它提供的起步依赖和自动配置。
起步依赖其实就是我们在 maven 里面写的依赖坐标,这样可以简化将具备某种功能的坐标打包一起导入。
自动配置是 spring boot 的核心重点,spring-boot-starter 这个东西本质就是 spring boot 的自动配置。自动配置,就是无须手动配置 xml,自动配置并管理 bean,可以简化开发过程。自动配置有如下几个关键的步骤:
基于 Java 代码的 Bean 配置
自动配置条件依赖
Bean 参数获取
Bean 的发现
Bean 的加载
下面来通过我们常用的一个 starter 例子 mybatis-spring-boot-starter 来讲述以下自动配置的实现过程。
基于 Java 代码的 Bean 配置
当我们通过 maven 导入 mybatis-spring-boot-starter 这个 jar 的坐标后,可以看到这个 jar 下面包括了很多相关的 jar,如图:
我们可以点开 mybatis-spring-boot-autoconfigure 这个 jar 包 ,可以从这个包名 autoconfigure 看出这个包是自动配置的意思,见名知意我们想要探究的自动配置原理就在这个包下面。我们照下图点开里面的 MybatisAutoConfiguration 这个自动配置类:
我们从类中截取关键的代码来看看:
可以看出,这个类里有很多注解,确实自动配置的实现原理基本就是靠这些注解来展开的。
@Configuration 和**@Bean**这两个注解一起使用就可以创建一个基于 java 代码的配置类,可以用来替代传统的 xml 配置文件。
@Configuration 表明这个类是一个配置类,这个注解的类可以看作是能生产让 Spring IoC 容器管理的 Bean 实例的工厂,也就是这个类里可以实例化对象并放在 spring 容器里,替代的就是以往的 xml 配置文件。
@Bean 注解的含义是方法返回的对象可以被注册到 spring 容器中,也就是会实例化一个对象放在 spring 容器里面 。
所以上图的 MybatisAutoConfiguration 这个类,自动帮我们生成了 SqlSessionFactory 和 SqlSessionTemplate 这些 Mybatis 的重要实例并交给 spring 容器管理,从而完成 bean 的自动注册。
自动配置条件依赖
从 MybatisAutoConfiguration 这个类中使用的注解可以看出,不光有**@Configuration 和 @Bean**这两个注解,还有其他的注解,而这些注解就是要完成自动配置的依赖条件。
这两个注解的含义就是要完成 Mybatis 的自动配置,需要在类路径中存在 SqlSessionFactory.class、SqlSessionFactoryBean.class 这两个类,同时需要存在 DataSource 这个 bean 也就是 DataSource 这个对象需要注入进去且这个 bean 完成自动注册。
下面列举一些常见的条件依赖注解:
注解
功能说明
@ConditionalOnBean
仅在当前上下文中(spring 容器)存在某个 bean 时,才会实例化这个 Bean
@ConditionalOnClass
某个 class 位于类路径上,才会实例化这个 Bean
@ConditionalOnExpression
当表达式为 true 的时候,才会实例化这个 Bean
@ConditionalOnMissingBean
仅在当前上下文中(spring 容器)不存在某个 bean 时,才会实例化这个 Bean
@ConditionalOnMissingClass
某个 class 在类路径上不存在的时候,才会实例化这个 Bean
@ConditionalOnNotWebApplication
不是 web 应用时才会实例化这个 Bean
@AutoConfigureAfter
在某个 bean 完成自动配置后实例化这个 bean
@AutoConfigureBefore
在某个 bean 完成自动配置前实例化这个 bean
Bean 参数获取
在项目中我们的 mybatis 通过 spring boot 完成自动配置是需要我们在在配置文件中提供数据源相关的配置参数,例如数据库驱动、连接 url、数据库用户名、密码等等。下面就来看看 spring boot 是如何读取 yml 或者 properites 配置文件的的属性来创建数据源对象的。
我们导入 mybatis-spring-boot-starter 这个 jar 包时也会同步导入一个 spring-boot-autoconfigure 包,点开这个包下的 jdbc 文件夹中有一个一个自动配置类 DataSourceAutoConfiguration,如图:
这个自动配置类中加了**@EnableConfigurationProperties**注解,这个注解的含义就是启用配置属性,就是启用括号里面的类中的属性,我们点开括号中的类:
可以看到这个类上加入了**@ConfigurationProperties 注解,这个注解的作用就是把 yml 或者 properties 配置文件中的配置参数信息封装到 @ConfigurationProperties 注解标注的 bean(即 DataSourceProperties**)的相应属性上。
@****EnableConfigurationProperties 注解的实际作用就是使**@ConfigurationProperties**注解生效。
Bean 的发现
spring boot 默认扫描启动类所在的包下的主类与子类的所有组件,但并没有包括依赖包也就是各种 starter 中的类,下面就来看看 starter 中的 bean 都是如何被发现的。
我们所创建的 Spring Boot 项目启动类中一般会加上**@SpringBootApplication**注解,我们就从这个注解点进去看看 bean 被发现的步骤:
点进去后可以看到如上三个重要注解:
@SpringBootConfiguration:作用就相当于**@Configuration**注解,被注解的类将成为一个 bean 配置类,表明其实启动类本质也是一个配置类。
@ComponentScan:作用就是自动扫描并加载符合条件的组件,但是不会扫描我们所加入的 starter 依赖包,最终将这些 bean 加载到 spring 容器中。
@EnableAutoConfiguration :含义就是启用自动配置,有了这个注解就可以自动将依赖中的 bean 创建出来。
所以我们要想知道 bean 是如何被发现的**@EnableAutoConfiguration**这个注解很重要,继续点进这个注解:
@****EnableAutoConfiguration 注解引入了**@Import 这个注解,这个注解为导入需要自动配置的组件,后面跟了一个 EnableAutoConfigurationImportSelector** 这个类,我们点进去看看:
EnableAutoConfigurationImportSelector 继承了 AutoConfigurationImportSelector 类也就是个选择器类,继续跟踪 AutoConfigurationImportSelector 类源码:
项目启动的时候我们 spring boot 框架会自动调用上图这个方法 getCandidateConfigurations 意思为获取候选配置项也就是从我们引入的 jar 包中去获取一些配置,而这个方法中又调用了 SpringFactoriesLoader 类的 loadFactoryNames 方法,继续跟踪源码:
我们可以看到 SpringFactoriesLoader 的 loadFactoryNames 静态方法可以从我们所有引入的 jar 包中读取 META-INF/spring.factories 文件,而自动配置的类的位置路径就在这个文件中进行配置:
spring.factories 文件内容如下:
这样 Spring Boot 就可以通过读取 META-INF/spring.factories 文件找到 MybatisAutoConfiguration 这个配置类的加载位置从而加载到 MybatisAutoConfiguration 这个配置类了,然后从配置类中发现 bean。
Bean 的加载
就是通过 spring boot 将一个普通类实例化然后交给 Spring 容器管理,通常有以下方法:
在 Spring Boot 应用中要让一个普通类交给 Spring 容器管理,通常有以下方法:
1、使用 @Configuration 与 @Bean 注解
2、使用 @Controller @Service @Repository @Component 注解标注该类并且启用 @ComponentScan 自动扫描
3、使用 @Import 方法
其中 Spring Boot 实现自动配置使用的是 @Import 注解这种方式,上面我们也讲解过 AutoConfigurationImportSelector 类的 selectImports 方法返回一组从 META-INF/spring.factories 文件中读取的 bean 的全类名,这样 Spring Boot 就可以加载到这些 Bean 并完成实例的创建工作。
总结
我们可以将自动配置的关键几步以及相应的注解总结如下:
1、@Configuration 与 @Bean:基于 Java 代码的 bean 配置
2、@Conditional:设置自动配置条件依赖
3、@EnableConfigurationProperties 与 @ConfigurationProperties:读取配置文件转换为 bean
4、@EnableAutoConfiguration 与 @Import:实现 bean 发现与加载
以上就是本次对 spring boot 自动配置 starter 完整过程的探究,后面会通过自定义 starter 来进一步巩固对自动配置 starter 的理解和应用。
评论