Spring提供了一系列starter来简化Maven配置。其核心原理也就是Maven和Gradle的依赖传递方案。当我们在我们的pom文件中增加对某个starter的依赖时,该starter的依赖也会自动的传递性被依赖进来。而且,很多starter也依赖了其他的starter。例如web starter就依赖了tomcat-starter,并且大多数starter基本都依赖了spring-boot-starter。
Spring Boot会根据类路径中的jar包、类,为jar包里的类自动配置,这样可以极大的减少配置的数量。简单点说就是它会根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中。自动配置充分的利用了spring 4.0的条件化配置特性,能够自动配置特定的Spring bean,用来启动某项特性。
Spring 4本身提供了很多已有的条件供直接使用,如:
@ConditionalOnBean @ConditionalOnClass @ConditionalOnExpression @ConditionalOnMissingBean @ConditionalOnMissingClass @ConditionalOnNotWebApplication 复制代码
自动配置充分的利用了spring4.0的条件化配置特性,那么,SpringBoot是如何实现自动配置的?Spring4中的条件化配置又是怎么运用到SpringBoot中的呢?这要从SpringBoot的启动类说起。SpringBoot应用通常有一个名为*Application的入口类,入口类中有一个main方法,这个方法其实就是一个标准的Java应用的入口方法。
一般在main方法中使用SpringApplication.run()来启动整个应用。值得注意的是,这个入口类要使用@SpringBootApplication注解声明。@SpringBootApplication是SpringBoot的核心注解,他是一个组合注解。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { // 略 } 复制代码
@SpringBootApplication
是一个组合注解,它主要包含 @SpringBootConfiguration、@EnableAutoConfiguration
等几个注解。也就是说可以直接在启动类中使用这些注解来代替 @SpringBootApplication
注解。关于SpringBoot中的Spring自动化配置主要是 @EnableAutoConfiguration
的功劳。该注解可以让SpringBoot根据类路径中的jar包依赖为当前项目进行自动配置。
至此,我们知道,SpringBoot的自动化配置主要是通过 @EnableAutoConfiguration
来实现的,因为我们在程序的启动入口使用了 @SpringBootApplication
注解,而该注解中组合了 @EnableAutoConfiguration
注解。所以,在启动类上使用 @EnableAutoConfiguration
注解,就会开启自动配置。
那么,本着刨根问底的原则,当然要知道 @EnableAutoConfiguration
又是如何实现自动化配置的,因为目前为止,我们还没有发现Spring 4中条件化配置的影子。
其实Spring框架本身也提供了几个名字为@Enable开头的Annotation定义。比如 @EnableScheduling、@EnableCaching、@EnableMBeanExport
等, @EnableAutoConfiguration
的理念和这些注解其实是一脉相承的。
@EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。 @EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。 @EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。 复制代码
下面是EnableAutoConfiguration注解的源码:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { //略 } 复制代码
观察 @EnableAutoConfiguration
可以发现,这里Import了 @EnableAutoConfigurationImportSelector
,这就是Spring Boot自动化配置的“始作俑者”。
至此,我们知道,至此,我们知道,由于我们在SpringBoot的启动类上使用了 @SpringBootApplication
注解,而该注解组合了 @EnableAutoConfiguration
注解, @EnableAutoConfiguration
是自动化配置的“始作俑者”,而 @EnableAutoConfiguratio
n中Import了 @EnableAutoConfigurationImportSelector
注解,该注解的内部实现已经很接近我们要找的“真相”了。 EnableAutoConfigurationImportSelector
的源码在这里就不贴了,感兴趣的可以直接去看一下,其实实现也比较简单,主要就是使用Spring4提供的的 SpringFactoriesLoader
工具类。通过 SpringFactoriesLoader.loadFactoryNames()
读取了ClassPath下面的 META-INF/spring.factories
文件。
EnableAutoConfigurationImportSelector
通过读 取spring.factories
中的key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration
的值。如 spring-boot-autoconfigure-1.5.1.RELEASE.jar
中的 spring.factories
文件包含以下内容:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=/ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,/ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,/ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,/ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,/ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,/ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,/ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,/ ...... org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration 复制代码
上面的 EnableAutoConfiguration
配置了多个类,这些都是SpringBoot中的自动配置相关类;在启动过程中会解析对应类配置信息。每个Configuation都定义了相关bean的实例化配置。都说明了哪些bean可以被自动配置,什么条件下可以自动配置,并把这些bean实例化出来。
如果我们新定义了一个starter的话,也要在该starter的jar包中提供 spring.factories文件,并且为其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类 复制代码
通过Spring 4的条件配置决定哪些bean可以被配置,将这些条件定义成具体的Configuation,然后将这些Configuation配置到spring.factories文件中,作为key: org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,这时候,容器在启动的时候,由于使用了EnableAutoConfiguration注解,该注解Import的EnableAutoConfigurationImportSelector会去扫描classpath下的所有spring.factories文件,然后进行bean的自动化配置。
所以,如果我们想要自定义一个starter的话,可以通过以上方式将自定义的starter中的bean自动化配置到Spring的上下文中,从而避免大量的配置