很多Spring开发者都知道@EnableTransactionManagement,它用来声明事务管理。@EnableWebMvc注释,它能启用SpringMVC,以及@EnableScheduling注解,它可以初始化一个调度器。
这些注解事实上都是简单的配置,通过@Import注解引入。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.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 {};
}
EnableAutoConfigurationImportSelector类使用了Spring Core包的SpringFactoriesLoader类的loadFactoryNamesof()方法。SpringFactoriesLoader会查询META-INF/spring.factories文件中包含的JAR文件,当找到spring.factories文件后,SpringFactoriesLoader将查询配置文件命名的属性。让我们来看看spring-boot-autoconfigugure JAR文件,它就包含了一个spring.factories文件,在这个文件中,可以看到一系列Spring Boot自动配置的列表,下面我们来看这些配置的细节,以MongoAutoConfiguration为例:
@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
private final MongoClientOptions options;
private final MongoClientFactory factory;
private MongoClient mongo;
public MongoAutoConfiguration(MongoProperties properties,
ObjectProvider options, Environment environment) {
this.options = options.getIfAvailable();
this.factory = new MongoClientFactory(properties, environment);
}
@PreDestroy
public void close() {
if (this.mongo != null) {
this.mongo.close();
}
}
@Bean
@ConditionalOnMissingBean
public MongoClient mongo() {
this.mongo = this.factory.createMongoClient(this.options);
return this.mongo;
}
}
这类进行了简单的Spring配置,声明了MongoDB所需典型Bean。这个类跟其它很多类一样,重度依赖于Spring Boot注解。
(1)@ConditionOnClass:激活一个配置,在类路径中只能存在一个到几个这样的类。
(2)@EnableConfigurationProperties:自动映射一个POJO到Spring Boot配置文件(默认是application.properties文件)的属性集。
(3)@ConditionalOnMissingBean:启用一个Bean定义,但必须是这个Bean之前未定义过才有效。
还可以使用@AutoConfigureBefore注释,@AutoConfigureAfter注释定义这些配置类的载入顺序。
下面看MongoProperties类,它是一个Spring Boot属性映射的例子:
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
private String host;
private int port = DBPort.PORT;
private String uri = "mongodb://localhost/test";
private String database;
// ... getters/ setters omitted
}
@ConfigurationProperties注解将POJO关联到指定前缀的每一个属性。例如:spring.data.mongodb.port属性将映射到这个类的端口属性,强烈建议Spring Boot开发者使用这种方式来删除与配置属性相关的瓶颈代码。
此注解使得只有在特定条件满足时才启用一些配置。以ConditionalOnException注释为例,它允许在Spring的EL表达式中写一个条件。
@Conditional(OnExpressionCondition.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface ConditionalOnExpression {
/**
* The SpEL expression to evaluate. Expression should return {@code true} if the
* condition passes or {@code false} if it fails.
*/
String value() default "true";
}
在这个类中,利用了@Conditional注解,条件在OnExpressionCondition类中定义:
public class OnExpressionCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
// ...
// we first get a handle on the EL context via the ConditionContext
boolean result = (Boolean) resolver.evaluate(expression, expressionContext);
// ...
// here we create a message the user will see when debugging
return new ConditionOutcome(result, message.toString());
}
}
最后欢迎大家访问我的个人网站:1024s