一、為什么SpringBoot產生於Spring4?
Spring4中增加了@Condition annotation, 使用該Annotation之后,在做依賴注入的時候,會檢測是否滿足某個條件來決定是否注入某個類。
@ConditionalOnBean(僅僅在當前上下文中存在某個對象時,才會實例化一個Bean)
@ConditionalOnClass(某個class位於類路徑上,才會實例化一個Bean)
@ConditionalOnExpression(當表達式為true的時候,才會實例化一個Bean)
@ConditionalOnMissingBean(僅僅在當前上下文中不存在某個對象時,才會實例化一個Bean)
@ConditionalOnMissingClass(某個class類路徑上不存在的時候,才會實例化一個Bean)
@ConditionalOnNotWebApplication(不是web應用)
ConditionEvaluator中的 shouldSkip方法則使用了 @Conditional中設置的 Condition類。Conditional
@Conditional是SpringFramework的功能,SpringBoot在它的基礎上定義了@ConditionalOnClass,@ConditionalOnProperty的一系列的注解來實現更豐富的內容。
觀察@ConditionalOnClass會發現它注解了@Conditional(OnClassCondition.class)。
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(OnClassCondition.class) public @interface ConditionalOnClass { Class<?>[] value() default {}; String[] name() default {}; }
OnClassCondition則繼承了SpringBootCondition,實現了Condition接口。
public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
查看SpringFramework的源碼會發現加載使用這些注解的入口在ConfigurationClassPostProcessor中,這個實現了BeanFactoryPostProcessor接口,前面介紹過,會嵌入到Spring的加載過程。
這個類主要是從ApplicationContext中取出Configuration注解的類並解析其中的注解,包括 @Conditional,@Import和 @Bean等。
解析 @Conditional 邏輯在ConfigurationClassParser類中,這里面用到了 ConditionEvaluator 這個類。
作者:wcong
鏈接:https://www.jianshu.com/p/1d0fb7cd8a26
二、@Enable*注解和屬性映射
@Enable*注解
@Enable*在Spring 3框架就引入了這些注解,用來替代XML配置文件。
很多Spring開發者都知道@EnableTransactionManagement注釋,它能夠聲明事務管理;@EnableWebMvc注釋,它能啟用Spring MVC;以及@EnableScheduling注釋,它可以初始化一個調度器。
這些注釋事實上都是簡單的配置,通過@Import注釋導入。@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import({ EnableAutoConfigurationImportSelector.class, AutoConfigurationPackages.Registrar.class }) public @interface EnableAutoConfiguration { /** * Exclude specific auto-configuration classes such that they will never be applied. */ Class<?>[] exclude() default {}; }
EnableAutoConfigurationImportSelector類使用了Spring Core包的SpringFactoriesLoader類的loadFactoryNamesof()方法。
SpringFactoriesLoader會查詢META-INF/spring.factories文件中包含的JAR文件。
當找到spring.factories文件后,SpringFactoriesLoader將查詢配置文件命名的屬性。在例子中,是org.springframework.boot.autoconfigure.EnableAutoConfiguration。屬性映射@ConfigurationProperties注解
@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屬性將映射到這個類的端口屬性。