Spring Boot 入门 - 进阶篇(7)- 自动配置(AutoConfigure)

自动配置是Spring Boot的最大亮点,完美的展示了CoC约定由于配置。Spring Boot能自动配置Spring各种子项目(Spring MVC, Spring Security, Spring Data, Spring Cloud, Spring Integration, Spring Batch等)以及第三方开源框架所需要定义的各种Bean。

Spring Boot内部定义了各种各样的XxxxAutoConfiguration配置类,预先定义好了各种所需的Bean。只有在特定的情况下这些配置类才会被起效。

[b](1)如何导入的自动配置类[/b]
查看源码可以看看自动配置类是如何被引入的。

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 下
[quote]# 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[/quote]

应用启动后是如何加载这些类的呢?
通过执行SpringApplication.run()方法,会把当前的SpringBootDemoApplication作为source传入而在SpringApplication类中还会读取spring.factories中的设置一并构建应用的Context。

spring-boot-1.5.1.RELEASE.jar/META-INF/spring.factories
[quote]# 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[/quote]

spring-boot-autoconfigure-1.5.1.RELEASE.jar/META-INF/spring.factories
[quote]# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer[/quote]

相应在做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);
}
}


[b](2)自动配置类内部构成[/b]

举例查看 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();
}

// ...

}


[b]条件配置[/b] 基于Spring的@Conditional,SpringBoot提供了丰富的条件配置:
[quote]@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应用环境下起效[/quote]
@Conditional({OnClassCondition.class})
public @interface ConditionalOnClass {
// ...
}

public class OnClassCondition extends SpringBootCondition implements ... {
// ...
// MatchType.PRESENT 判断classpath里是否存在指定类
}

public abstract class SpringBootCondition implements Condition {
// ...
}


[b]执行顺序[/b]
[quote]@AutoConfigureAfter:在指定的配置类初始化后再加载
@AutoConfigureBefore:在指定的配置类初始化前加载
@AutoConfigureOrder:数越小越先初始化[/quote]

[b](3)查看项目实际配置了什么[/b]
运行时开启DEBUG模式后即可在控制台看到具体的自动配置结果。

/src/main/resources/application.properties
[quote]debug=true[/quote]

[quote]=========================
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[/quote]

比如可以看到SpringBoot默认开启了:
[quote]DispatcherServletAutoConfiguration 注册DispatcherServlet
EmbeddedServletContainerAutoConfiguration.EmbeddedTomcat 注册Tomcat容器
ErrorMvcAutoConfiguration 注册异常处理器
HttpEncodingAutoConfiguration 注册编码过滤器CharacterEncodingFilter
HttpMessageConvertersAutoConfiguration 注册json或者xml处理器
JacksonAutoConfiguration 注册json对象解析器
MultipartAutoConfiguration 注册文件传输处理器
TransactionAutoConfiguration 注册事物管理处理器
ValidationAutoConfiguration 注册数据校验处理器
WebMvcAutoConfiguration 注册SpringMvc相关处理器[/quote]

[b](4)关闭自动配置[/b]

[b]全体无效化[/b]

a)使用@Configuration @ComponentScan 代替 @SpringBootApplication。

b)参数设置
src/main/resources/application.properties
[quote]spring.boot.enableautoconfiguration=false[/quote]

部分无效化

@SpringBootApplication(exclude=HibernateJpaAutoConfiguration.class)


src/main/resources/application.properties
[quote]spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration[/quote]

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})


src/main/resources/application.properties
[quote]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[/quote]

参考:
http://qiita.com/kazuki43zoo/items/8645d9765edd11c6f1dd
http://d.hatena.ne.jp/Kazuhira/20170219/1487513127

你可能感兴趣的:(SpringBoot)