SpringBoot起步依赖和自动配置
一、起步依赖
1. 是什么
本质上是一个Maven项目对象模型(Project Object Model, POM), 定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。 比如:
- spring-boot-dependencies
-
^ spring-boot-parent
-
^ spring-boot-starters
-
^ spring-boot-starter-web
spring boot起步依赖的名字具有很大的可读性,一般见到名字就知道其功能。 使用起步依赖 = 起步依赖+依赖的传递依赖(注意:这些依赖的版本是确定好了的, 经过实践验证的可用的,自己不需要再添加), 可以通过$ mvn dependency:tree
查看依赖树。
2. 怎么用
<!--添加web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除不需要的传递依赖-->
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
<!--如果想加其他依赖,直接再加dependency元素
如果起步依赖包括想要加的依赖,但是版本与想使用的版本不同,
可以先排除掉老的依赖,再加dependency元素添加新依赖。
Maven倾向于使用最近的依赖,Gradle倾向于使用库的最新版本。
-->
二、自动配置
1. 是什么
Spring Boot的自动配置是应用程序启动时,spring boot框架自动检测 classpath里的Bean来进行配置的一种机制。
2. 怎么用
通过在配置类里使用@EnableAutoConfiguration
或者@SpringBootApplication
注解 开启组件扫描和自动配置。 通过@SpringBootApplication
的exclude参数关闭特定 的自动配置。@SpringBootApplication(exclude = XAutoConfiguration.class)
3. 怎么实现的
(参考《JavaEE开发的JavaEE开发的颠覆者-SpringBoot实战》一书)
源码可以查看spring-boot-autoconfigure-1.5.6.RELEASE.jar包
1).@EnableAutoConfiguration注解
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
这里起关键作用的是@Import注解导入的配置功能。 EnableAutoConfigurationImportSelector使用SpringFactoriesLoader.loadFactoryNames 方法来扫描具有META-INF/spring.factories文件里的jar包,spring.factories文件中声明了 有哪些自动配置。 打开AutoConfiguration的Java源文件,可以看到有 @ConditionalOnClass @ConditionalOnBean @ConditionalOnMissingBean @ConditionalOnJava 等这些注解
这些注解都是组合了@Conditional元注解,例如@ConditionalOnWebApplication注解:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnWebApplicationCondition.class)
public @interface ConditionalOnWebApplication {
}
进一步可以看看OnWebApplicationCondition条件是怎么构造的:
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
class OnWebApplicationCondition extends SpringBootCondition {
private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context."
+ "support.GenericWebApplicationContext";
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
boolean required = metadata
.isAnnotated(ConditionalOnWebApplication.class.getName());
ConditionOutcome outcome = isWebApplication(context, metadata, required);
if (required && !outcome.isMatch()) {
return ConditionOutcome.noMatch(outcome.getConditionMessage());
}
if (!required && outcome.isMatch()) {
return ConditionOutcome.noMatch(outcome.getConditionMessage());
}
return ConditionOutcome.match(outcome.getConditionMessage());
}
private ConditionOutcome isWebApplication(ConditionContext context,
AnnotatedTypeMetadata metadata, boolean required) {
//此处为具体判断方法,代码省略
}