@Conditional 能解决什么问题
可以使Bean在满足一定的条件Condition
下才进行装配。
条件Condition如何定义?
实现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
方法提供了两个参数,是接口类型:
ConditionContext
与 AnnotatedTypeMetadata
ConditionContext接口
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
通过ConditionContext,我们可以做到如下几点:
方法 | 作用 |
---|---|
getRegistry() | 借助返回的BeanDefinitionRegistry检查bean的定义 |
getBeanFactory() | 借助返回的ConfigrableListableBeanFactory检查是否存在,甚至检查bean的属性 |
getEnvironment() | 借助返回Environment检查环境变量是否存在以及读取它的值是什么 |
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
会根据ACondition
的matches()
方法的返回值来决定能否注册该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
打印当前所有已经注册的BeanID。 - 判断BeanID为
BeforeAConditionBean
的Bean是否已经创建。 - 判断需要创建的Bean是否带有
AConditionAnno
注解。
2.为Bean加上条件注解@Conditional
@Service
@Conditional(ACondition.class)
@AConditionAnno
public class AConditionServiceImpl implements ConditionService{
@Override
public String getName() {
return this.getClass().getName();
}
}
3.测试类主方法
@RunWith(SpringRunner.class)
@SpringBootTest
public class ConditionalTest {
@Autowired
ConditionService conditionService;
@Test
public void test(){
System.out.println(conditionService.getName());
}
}
不出意外,@Autowired
是可以装配成功的。
如果把AConditionServiceImpl
类上的@AConditionAnno
注解去掉,那么测试类报错,@Autowired
找不到Bean。
网友评论