《Spring實戰》-第三章:Bean的高級裝配(2)-條件化Bean

慢慢來比較快,虛心學技術

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();

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章