相对于spring来说,spring boot最大的特点就是提供了大量的“starter”简化了配置,和尽可能的自动配置,那么我们今天就来说说spring boot是如何做到自动配置的。
我们都知道,启动一个spring boot应用程序是通过在启动类里面的一个main方法实现的:
@SpringBootApplication public class TestApplication { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } }
在这个类里面,通过SpringApplication的run方法实例化一个spring容器。但是最关键的就是标注在类上面的@SpringBootApplication注解,这个注解是一个复合注解,可以进去看一下源码:
在spring中我们接触过很多@EnableXxx型的注解,如@EnableTransactionManager(启用事务管理器)、@EnableWebMvc(引入MVC框架在Spring应用中需要用到的所有bean)等,这些@EnableXxx的作用就是启用某些配置功能,那么@EnableAutoConfiguration这个注解就是启用了自动配置的功能。点进去看一下这个注解:
这里有一个@Import注解,这个注解的作用就是导入某些类进来,例如导入配置类等。在这里导入的是AutoConfigurationImportSelector这个类,可以把这个类理解成自动导入的选择器,进去那个类后,重点看getCandidateConfiguration()方法:
SpringFatoriesLoader.loadFactoryNames()方法会返回一个List集合,集合中存放的是String的数据,实际上configurations中的信息就是所有的自动配置类的完整类名,然后把这个集合返回给spring,然后交由spring解析,来完整这些自动配置。
那么是从哪里得到的完整类名呢?继续跟踪loadFactoryNames()方法:
再看loadSpringFactories方法:
我们以mybatis的starter为例,从本地仓库找到org目录,进入到org/mybatis/spring/boot/
里面有一个mybatis-spring-boot-autoconfigure文件夹,这里面就是存放着不同的版本,选择一个版本进去后,里面存放的就是跟自动配置有关的文件:
解压里面的一个jar包:
果然,META-INF目录出现了,进去看看:
里面有一个spring.factories文件,用记事本打开:
注释标注着这是一个自动配置,下面是像“key = value”一样的格式,""是一个换行符,作用是换行,重点就是这个value:org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration。这个就是mybatis自动配置的入口点了,这个完整类名也会通过上面的loadFactoryNames方法存放到List集合中,从而加载并初始化。
那么MybatisAutoConfiguration这个类在哪里呢?有什么作用呢?我们回到解压后的jar包下,看到META-INF文件夹下面还有一个org目录,根据完整类名进入到相应的目录,即org/mybatis/spring/boot/autoconfigure/中:
里面也有一个MybatisAutoConfiguration.class文件,用idea反编译出来:
@Configuration:就是标注当前类是一个配置类
@ConditionalOnClass:称为条件注解,因为不是说把这个配置类一加载进来就立马初始化这个它,而是要满足某一些条件的,像这个注解中引入了SqlSessionFactory和SqlSessionFactoryBean两个class对象,所以条件就是要满足这两个类在classpath或者称之为类路径的前提下,我们才初始化这个配置类。什么情况下这两个类会在类路径下呢?就是项目依赖了mybatis的jar包,这两个类自然就存在类路径下了。
@ConditionalOnBean:也是一个条件注解,和前一个差不多,意思是要指定的bean存在ioc容器下的前提下,才会初始化这个配置类。
@EnableConfigurationProperties:作用是启用了一些配置的属性。
@AutoConfigureAfter:意思就是要在指定的类加载完成才会去初始化这个配置类,这里指定的就是DatasourceAutoConfiguration这个class对象。
在这个配置类中,我们可以看到一些在spring中需要配置的bean,如SqlSessionFactory:
所以在使用mybatis的starter的时候,就不需要再手动地配置这些相关的bean了。
同时,在这个方法上,也有一个@ConditionalOnMissingBean条件注解,这个注解的意思是,当ioc容器中不存在这个bean的时候(这里指的是SqlSessionFactory这个bean),才会执行这个方法,来初始化这个SqlSessionFactory。