从@SpringBootApplication注解说起 SpringBoot
会根据类路径下的类自动配置,省去了编写繁琐的xml
配置文件。原本基于xml
配置bean
的方式编程基于Java代码,并且可以条件化配置,根据不同的场景配置也随之不同。是不是很智能
为了清楚SpringBoot
自动配置的原理,我们从最简单的SpringBoot
的启动类说起,看一个简单的启动实例
1 2 3 4 5 6 @SpringBootApplication public class Application { public static void main (String[] args) { SpringApplication.run(Application.class ) ; } }
SpringBoot
应用的启动很简单,就是一个main
方法,然后执行SpringApplication
的run方法。先不关心run方法是怎么执行的。我们先看SpringBoot
应用的核心注解@SpringBootApplication
1 2 3 4 5 6 7 8 9 10 11 12 @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 { ..... }
查看该注解的源代码可知,这是一个组合注解。
分别查看每个注解的含义
@SpringBootConfiguration
1 2 3 4 5 6 @Target ({ElementType.TYPE})@Retention (RetentionPolicy.RUNTIME)@Documented @Configuration public @interface SpringBootConfiguration {}
可知该注解就是@Configuration
注解,该注解什么这个一个配置类,在SpringBoot
中很常见。
@CompontScan
注解指定哪些包扫描或者不扫描。
使SpringBoot
应用拥有自动配置魔法的注解是@EnableAutoConfiguraion
。该注解可以让SpringBoot根据类路径中的依赖为当前项目进行自动配置 ,所以SpringBoot可以自动配置主要是因为SpringBoot应用上的@EnableAutoConfiguraion注解来实现的,所以在启动类上加入该注解,就会开启自动配置。
那么,这个注解是如何实现自动化配置的呢。接下来我们要一探究竟。
自动配置背后的注解 1 2 3 4 5 6 7 8 9 @Target (ElementType.TYPE)@Retention (RetentionPolicy.RUNTIME)@Documented @Inherited @AutoConfigurationPackage @Import (AutoConfigurationImportSelector.class ) public @interface EnableAutoConfiguration { ..... }
该注解也是一个组合注解,这里有一个@Import(AutoConfigurationImportSelector.class)
,那么@Import
注解的作用是什么呢,查看@Import
的源码注释,写着Indicates one or more {@link Configuration @Configuration} classes to import.Provides functionality equivalent to the {@code <import/>} element in Spring XML.
,注释表明这个注解指明了要导入的配置类,在功能上和Spring XML配置
中的<import>
相同
那这里@Import
导入的一个AutoConfigurationImportSelector
又什么作用呢?根据下面注释中的内容可以知道,@Import
允许导入ImportSelector,ImportBeanDefinitionRegistrar
的实现类,还有普通的类(在版本4.2后)
1 Allows for importing {@code @Configuration } classes , {@link ImportSelector} and {@link ImportBeanDefinitionRegistrar} implementations , as well as regular component classes (as of 4.2 ; analogous to {@link AnnotationConfigApplicationContext#register}).
到了这里,说一个与@Import注解相关的东西,Spring框架本身提供了几个以Enable打头的注解,根据名字可知这是开启某个功能,比如@EnableScheduling
、@EnableCaching
、@EnableMBeanExport
等,@EnableAutoConfiguration
的理念和这些注解其实是相同的的。
@EnableScheduling
是通过@Import
将Spring调度框架相关的bean定义都加载到IoC容器。@EnableMBeanExport
是通过@Import
将JMX相关的bean定义加载到IoC容器。
@EnableAutoConfiguration
也是借助@Import
的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。
接下来关注EnableAutoConfigurationImportSelector 这个作用是什么。主要就是使用Spring 4 提供的的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
文件包含以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
如果我们新定义了一个starter
的话,也要在该starter
的jar
包中提供 META-INFO/spring.factories
文件,并且为其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration
对应的配置类
从EnableAutoConfiguration
寻找一个配置类CacheAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Configuration @ConditionalOnClass (CacheManager.class ) @ConditionalOnBean (CacheAspectSupport .class ) @ConditionalOnMissingBean (value = CacheManager.class , name = "cacheResolver" )@EnableConfigurationProperties (CacheProperties.class ) @AutoConfigureAfter ( { CouchbaseAutoConfiguration.class , HazelcastAutoConfiguration .class , HibernateJpaAutoConfiguration .class , RedisAutoConfiguration .class }) @Import (CacheConfigurationImportSelector .class ) public class CacheAutoConfiguration { @Bean @ConditionalOnMissingBean public CacheManagerCustomizers cacheManagerCustomizers ( ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) { return new CacheManagerCustomizers(customizers.getIfAvailable()); } ....... }
这是一个@Configuration
配置类,包含@Bean
的方法的返回值会注册为一个bean
在这个类和方法上我们看到很多条件配置注解
条件配置主要的注解是@Conditional
,这个注解指定一个实现了Condition
的类,类中实现了matchs
方法,如果方法返回true
,被@Conditional
修饰的类或者方法才会创建bean
。为了方便Spring4
中已经帮我们实现了一些常用的条件配置注解
1 2 3 4 5 6 @ConditionalOnBean @ConditionalOnClass @ConditionalOnExpression @ConditionalOnMissingBean @ConditionalOnMissingClass @ConditionalOnNotWebApplication
至此,我们已经分析了SpringBoot
中自动化配置的基本原理,接下来我们会编写一个spring-boot-starter