@Configuration和@Bean
Spring提供了注解@Configuration和@Bean注解用來配置多個Bean,在以前的Spring項目中可以通過xml的方式配置:
<beans> <bean id=”xxxBean” class="aaa.bbb.xxxBean"></bean> </beans>
采用Configuration注解的方式如下:
//@SpringBootConfiguration @Configuration public class TestConfiguration { @Bean public EncodingConvert createUTF8EncodingConvert(){ return new UTF8EncodingConvert(); } @Bean public EncodingConvert createGBKEncodingConvert(){ return new GBKEncodingConvert(); } }
上面代碼中TestConfiguration類使用注解@ Configuration,向Spring表明這是一個配置類,類里的含有@Bean注解的方法都會被Spring調用,返回對象將會為Spring容器管理的Bean,注解@Bean可以給Bean指定一個名稱,如@Bean(“xxxBean”),如不指定,則將會以該方法名作為Bean的名稱
條件裝配
Spting Boot提供一系列@ConditionalOnXXX的注解用於不同場景下的Bean裝配。基本上通過注解名稱就能明白用途,@ConditionalOnXXX注解可以作用於類或者方法上。
1.作用用於類上,需要和 @Configuration注解一起使用,決定該配置類是否生效
2.作用於方法上,需要和@Bean注解一起使用,判斷該@Bean是否生成
Bean條件裝配
Spring Boot可以通過有沒有指定Bean來決定是否配置當前Bean,
使用@ConditionalOnBean,在當前上下文中存在某個對象時,才會實例化當前Bean;
使用@ConditionalOnMissingBean,在當前上下文中不存在某個對象時,才會實例化當前Bean。
@Configuration @ConditionalOnBean(PropertiesConfig.class) public class TestConfiguration { @Bean @ConditionalOnMissingBean public EncodingConvert createUTF8EncodingConvert(){ return new UTF8EncodingConvert(); } @Bean public EncodingConvert createGBKEncodingConvert(){ return new GBKEncodingConvert(); } }
TestConfiguration配置生效的前提是當前上下文中已經配置了PropertiesConfig。
如果當前上下文中沒有UTF8EncodingConvert類型Bean,則調用createUTF8EncodingConvert創建。
Class條件裝配
Class條件裝配是按照某個類是否在Classpath中來判斷是否需要配置Bean。
@ConditionalOnClass:表示classpath有指定的類時,配置才生效
@ConditionalOnMissingClass:表示當classpath中沒有指定類,則配置生效
@Configuration @ConditionalOnClass(JestClient.class) //@ConditionalOnClass(name="com.sl.springbootdemo.JestClient") public class JestAutoConfiguration{ }
Environment裝配
Spring Boot可以根據Environment屬性來決定是否實例化Bean,通過@ConditionalOnProperty注解來實現。根據注解屬性name讀取Spring Boot的Environment的變量包含的屬性 ,再根據屬性值與注解屬性havingValue的值比較,判斷否實例化Bean,如果沒有指定注解屬性havingValue,name只要environment屬性值不為false,都會實例化Bean。MatchIfMissing=true,表示如果evironment沒有包含message.center.enavled屬性,也會實例化Bean,默認是false。
@Bean @ConditionalOnProperty(name="com.sl.Encoding",havingValue = "GBK",matchIfMissing = false) public EncodingConvert createGBKEncodingConvert(){ return new GBKEncodingConvert(); }
其他條件裝配注解:
@ConditionalOnExpression :當表達式為true時,才會實例化一個Bean,支持SpEL表達式
@ConditionalOnNotWebApplication:表示不是web應用,才會實例化一個Bean
Condition接口(自定義條件裝配)
當Spring Boot提供的一些列@ConditionalOnXXX注解無法滿足需求時,也可以手動構造一個Condition實現,使用注解@Conditional來引用Condition實現。
Condition接口定義:
@FunctionalInterface public interface Condition { /** * Determine if the condition matches. * @param context the condition context * @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class} * or {@link org.springframework.core.type.MethodMetadata method} being checked * @return {@code true} if the condition matches and the component can be registered, * or {@code false} to veto the annotated component's registration */ boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }
參數ConditionContext類可以獲取用於幫助條件判斷的輔助類:
1.Environment:讀取系統屬性、環境變量、配置參數等。
2.ResourceLoader:加載判斷資源文件
3.ConfigurableListableBeanFactory:Srping容器
下面是一個實現示例,當application.properties配置文件中存在配置file.encoding=GBK時才創建Bean實例
public class GBKCondition implements Condition { public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){ String encoding = context.getEnvironment().getProperty("file.encoding"); if("gbk".equals(encoding.toLowerCase())){ return true; } return false; } }
使用:
@Bean @Conditional(GBKCondition.class) //使用自定義Condition public EncodingConvert createGBKEncodingConvert(){ return new GBKEncodingConvert(); }