Spring Boot内部定义了各种各样的XxxxAutoConfiguration配置类,预先定义好了各种所需的Bean。只有在特定的情况下这些配置类才会被起效。
(1)如何导入的自动配置类
查看源码可以看看自动配置类是如何被引入的。
a) 应用入口
@SpringBootApplication public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } }
b) 类注解 @SpringBootApplication = @EnableAutoConfiguration + @ComponentScan + @Configuration
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { // ... } @Configuration public @interface SpringBootConfiguration { // ... }
c)开启自动配置注解 @EnableAutoConfiguration
@AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { // ... }
d)导入配置类 EnableAutoConfigurationImportSelector extends AutoConfigurationImportSelector
在AutoConfigurationImportSelector类中可以看到通过 SpringFactoriesLoader.loadFactoryNames()
把 spring-boot-autoconfigure-1.5.1.RELEASE.jar/META-INF/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.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
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.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
应用启动后是如何加载这些类的呢?
通过执行SpringApplication.run()方法,会把当前的SpringBootDemoApplication作为source传入而在SpringApplication类中还会读取spring.factories中的设置一并构建应用的Context。
spring-boot-1.5.1.RELEASE.jar/META-INF/spring.factories
引用
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
spring-boot-autoconfigure-1.5.1.RELEASE.jar/META-INF/spring.factories
引用
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
相应在做war时也是把当前的SpringBootDemoApplication作为source传给了ServletInitializer。
public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootDemoApplication.class); } }
配置类也可自行导入
@Configuration @Import({ DispatcherServletAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, ErrorMvcAutoConfiguration.class, HttpEncodingAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, MultipartAutoConfiguration.class, ServerPropertiesAutoConfiguration.class, WebMvcAutoConfiguration.class }) @ComponentScan public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); } }
(2)自动配置类内部构成
举例查看 org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { @Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); } // ... }
条件配置 基于Spring的@Conditional,SpringBoot提供了丰富的条件配置:
引用
@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
@Conditional({OnClassCondition.class}) public @interface ConditionalOnClass { // ... }
public class OnClassCondition extends SpringBootCondition implements ... { // ... // MatchType.PRESENT 判断classpath里是否存在指定类 }
public abstract class SpringBootCondition implements Condition { // ... }
执行顺序
引用
@AutoConfigureAfter:在指定的配置类初始化后再加载
@AutoConfigureBefore:在指定的配置类初始化前加载
@AutoConfigureOrder:数越小越先初始化
@AutoConfigureBefore:在指定的配置类初始化前加载
@AutoConfigureOrder:数越小越先初始化
(3)查看项目实际配置了什么
运行时开启DEBUG模式后即可在控制台看到具体的自动配置结果。
/src/main/resources/application.properties
引用
debug=true
引用
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:
-----------------
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class
(OnClassCondition)
- @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class
(OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
.......
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory'
(OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)
.......
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
AUTO-CONFIGURATION REPORT
=========================
Positive matches:
-----------------
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class
(OnClassCondition)
- @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched:
- @ConditionalOnClass found required class 'javax.servlet.ServletRegistration'; @ConditionalOnMissingClass did not find unwanted class
(OnClassCondition)
- Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition)
.......
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory'
(OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)
.......
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
比如可以看到SpringBoot默认开启了:
引用
DispatcherServletAutoConfiguration 注册DispatcherServlet
EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat 注册Tomcat容器
ErrorMvcAutoConfiguration 注册异常处理器
HttpEncodingAutoConfiguration 注册编码过滤器CharacterEncodingFilter
HttpMessageConvertersAutoConfiguration 注册json或者xml处理器
JacksonAutoConfiguration 注册json对象解析器
MultipartAutoConfiguration 注册文件传输处理器
TransactionAutoConfiguration 注册事物管理处理器
ValidationAutoConfiguration 注册数据校验处理器
WebMvcAutoConfiguration 注册SpringMvc相关处理器
EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat 注册Tomcat容器
ErrorMvcAutoConfiguration 注册异常处理器
HttpEncodingAutoConfiguration 注册编码过滤器CharacterEncodingFilter
HttpMessageConvertersAutoConfiguration 注册json或者xml处理器
JacksonAutoConfiguration 注册json对象解析器
MultipartAutoConfiguration 注册文件传输处理器
TransactionAutoConfiguration 注册事物管理处理器
ValidationAutoConfiguration 注册数据校验处理器
WebMvcAutoConfiguration 注册SpringMvc相关处理器
(4)关闭自动配置
全体无效化
a)使用@Configuration @ComponentScan 代替 @SpringBootApplication。
b)参数设置
src/main/resources/application.properties
引用
spring.boot.enableautoconfiguration=false
部分无效化
@SpringBootApplication(exclude=HibernateJpaAutoConfiguration.class)
或
src/main/resources/application.properties
引用
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
或
src/main/resources/application.properties
引用
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
参考:
http://qiita.com/kazuki43zoo/items/8645d9765edd11c6f1dd
http://d.hatena.ne.jp/Kazuhira/20170219/1487513127