慢慢來比較快,虛心學技術
1、什麼是條件化Bean
在第一節中說到的profile限定了特殊環境下的Bean裝載,但是有時候只根據環境進行Bean裝配的選擇並不一定能滿足我們的需求,所以Spring4提供了更加細化的條件話配置Bean,用於對特定條件纔可以進行裝配的Bean進行配置
2、怎麼條件化配置Bean
條件化配置Bean主要依賴於一個註解和一個接口:
@Conditional(MathIsProd.class)---條件判斷註解
Condition接口----------------@Conditional中的條件類必須實現的接口,提供了match方法,進行條件邏輯的編寫
系統進行Bean裝配時,遇到@Conditional會先對其所包含的條件類執行match方法,如果方法返回爲true,則對該bean進行裝配,如果方法返回爲false,則不對該bean進行裝配
簡單實現:利用@Conditional間接實現@Profile("prod")功能
//基本類
@Component
public class BaseBean {
private String name="BaseBean";
public void setName(String name){
this.name = name;
}
}
//接口
public interface BaseService {
void update();
}
//接口實現類1
@Component
public class BaseServiceImpl1 implements BaseService {
@Autowired
private BaseBean baseBean;
@Override
public void update() {
System.out.println("BaseServiceImpl1 "+baseBean.getName());
}
}
//接口實現類2
@Component
public class BaseServiceImpl2 implements BaseService {
@Autowired
private BaseBean baseBean;
@Override
public void update() {
System.out.println("BaseServiceImpl2 "+baseBean.getName());
}
}
//測試類:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,classes = {ComponentConfig.class})
public class AppComponentTest {
@Autowired
private ApplicationContext applicationContext;
//注入baseService
@Autowired
private BaseService baseService;
@Test
public void testPrimary(){
baseService.update();
}
}
//測試結果:注入失敗,BaseService不止有一個實現類
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.my.spring.service.BaseService' available:
expected single matching bean but found 2: baseServiceImpl1,baseServiceImpl2
代碼1.8中的match方法參數
AnnotatedTypeMetadata:封裝了使用@Conditional註解的類的信息
ConditionContext:封裝了系統環境信息以及BeanFactory等各種實現,可以用來作爲條件信息的判斷
其中ConditionContext有以下常用方法:
- getRegistry() --------------返回BeanDefinitionRegistry,用於 檢查 bean 定義;
- getBeanFactory()---------返回ConfigurableListableBeanFactory ,用於檢查 bean 是否存在,甚至探查 bean 的屬性;
- getEnvironment() --------返回Environment,用於 檢查環境變量是否存在以及它的值是什麼;
- getResourceLoader() ---返回ResourceLoader 所加載的資源;
- getClassLoader() ---------返回ClassLoader 加載並檢查類是否存在。
注:實際上@Profile同樣註解使用了@Conditional註解,且使用ProfileCondition.class作爲其條件判斷類,源碼如下,有興趣自行查看:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
/**
* The set of profiles for which the annotated component should be registered.
*/
String[] value();
}