@Conditional 能解決什么問題
可以使Bean在滿足一定的條件Condition
下才進(jìn)行裝配欺缘。
條件Condition如何定義挤安?
實(shí)現(xiàn)Condition
接口,重寫matches()
方法络凿。
返回true
則條件成立,否則不成立絮记。
代碼如下:
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class ACondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//doSomething
}
}
可以看到matches
方法提供了兩個(gè)參數(shù)怨愤,是接口類型:
ConditionContext
與 AnnotatedTypeMetadata
ConditionContext接口
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
通過ConditionContext,我們可以做到如下幾點(diǎn):
方法 | 作用 |
---|---|
getRegistry() | 借助返回的BeanDefinitionRegistry檢查bean的定義 |
getBeanFactory() | 借助返回的ConfigrableListableBeanFactory檢查是否存在篮愉,甚至檢查bean的屬性 |
getEnvironment() | 借助返回Environment檢查環(huán)境變量是否存在以及讀取它的值是什么 |
getResourceLoader() | 讀取并檢查它返回的ResourceLoader所加載的資源 |
getClassLoader() | 借助它的返回的ClassLoader加載并檢查類是否存在 |
AnnotatedTypeMetadata接口
public interface AnnotatedTypeMetadata {
boolean isAnnotated(String annotationType);
Map<String, Object> getAnnotationAttributes(String annotationType);
Map<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString);
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType);
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString);
}
AnnotatedTypeMetadata
的isAnnotated()
方法差导,能夠判斷帶有@Bean
注解的方法是否有別的注解。其他的方法颠蕴,能夠獲取@Bean
注解的方法上其他注解的屬性助析。
@Conditional 如何使用
直接上代碼:
@Service
@Conditional(ACondition.class)
@AConditionAnno
public class AConditionServiceImpl implements ConditionService{
@Override
public String getName() {
return this.getClass().getName();
}
}
用法為:@Conditional(Condition.class)
加上之后,SpringAConditionServiceImpl
會(huì)根據(jù)ACondition
的matches()
方法的返回值來決定能否注冊(cè)該Bean寡键。
Demo
1.定義條件Condition
public class ACondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
for (String name:conditionContext.getRegistry().getBeanDefinitionNames()
) {
System.out.println(name);
}
System.out.println(conditionContext.getBeanFactory().containsBean("BeforeAConditionBean")
+"/"+annotatedTypeMetadata.isAnnotated(AConditionAnno.class.getName()));
return
annotatedTypeMetadata.isAnnotated(AConditionAnno.class.getName());
}
}
上面的代碼中:
- 通過
ConditionContext
打印當(dāng)前所有已經(jīng)注冊(cè)的BeanID雪隧。 - 判斷BeanID為
BeforeAConditionBean
的Bean是否已經(jīng)創(chuàng)建膀跌。 - 判斷需要?jiǎng)?chuàng)建的Bean是否帶有
AConditionAnno
注解。
2.為Bean加上條件注解@Conditional
@Service
@Conditional(ACondition.class)
@AConditionAnno
public class AConditionServiceImpl implements ConditionService{
@Override
public String getName() {
return this.getClass().getName();
}
}
3.測(cè)試類主方法
@RunWith(SpringRunner.class)
@SpringBootTest
public class ConditionalTest {
@Autowired
ConditionService conditionService;
@Test
public void test(){
System.out.println(conditionService.getName());
}
}
不出意外劫流,@Autowired
是可以裝配成功的丛忆。
如果把AConditionServiceImpl
類上的@AConditionAnno
注解去掉,那么測(cè)試類報(bào)錯(cuò)熄诡,@Autowired
找不到Bean。