@Conditional注解,官方解釋為:“隻有當所有指定的條件都滿足是,元件才可以注冊”,主要的用處是在建立bean時增加一系列限制條件,在條件通過時,才可以成功建立bean。
Conditional的聲明如下:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
接收的參數是一個數組,數組元素是Condition類型,Condition是一個接口:
public interface Condition{
/** Determine if the condition matches.
* @param context the condition context
* @param metadata meta-data of the {@link AnnotationMetadata class} or
* {@link Method method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
boolean matches(ConditionContext context, AnnotatedTypeMedata metadata);
}
當要自定義元件注冊規則時,編寫一個Condition的實作類即可,在實作類中定義通過的規則:
public class MyCondition1 implements Condition {
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//類加載器
ClassLoader classLoader = conditionContext.getClassLoader();
//目前運作環境
Environment environment = conditionContext.getEnvironment();
//bean定義的注冊類
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//資源加載器
ResourceLoader resourceLoader = conditionContext.getResourceLoader();
if(registry.containsBeanDefinition("person")){
return true;
}
return false;
}
}
上述代碼是我編寫的一個Condition的實作類,規則是當容器中存在一個名為person的bean時,條件生效。可以通過conditionContext來擷取更多的資訊,用于自定義條件。
另外,我還定義了一個Condition的實作類,判斷條件則和第一個的相反,在配置類中應用上@Condition
//配置類
@Configuration
public class MyConfig3 {
//@Lazy
@Bean("person")
public Person person(){
Person person = new Person("張三",20);
System.out.println(person);
return person;
}
@Conditional({MyCondition1.class})
@Bean
public Person p1(){
Person person = new Person("李四",21);
System.out.println(person);
return person;
}
@Conditional({MyCondition2.class})
@Bean
public Person p2(){
Person person = new Person("王五",22);
System.out.println(person);
return person;
}
}
//測試類
public class AnnotationTest {
@Test
public void testCondition(){
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig3.class);
}
}
輸出結果:

配置類的代碼中,我将@Lazy注解給注釋掉了,如果放開該注釋,那麼,輸出就隻會是Person{name='王五',22},因為容器在建立時,因懶加載的緣故,person這個bean并沒有被加載到容器當中,是以,另外一個條件生效,輸出Person{name='王五',22}這樣的結果