@Conditional条件化Bean装配

2018-09-05  本文已影响0人  妖云小离

@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方法提供了两个参数,是接口类型:
ConditionContextAnnotatedTypeMetadata

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

}

AnnotatedTypeMetadataisAnnotated()方法,能够判断带有@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会根据AConditionmatches()方法的返回值来决定能否注册该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());
    }
}

上面的代码中:

  1. 通过ConditionContext打印当前所有已经注册的BeanID。
  2. 判断BeanID为BeforeAConditionBean的Bean是否已经创建。
  3. 判断需要创建的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。

上一篇 下一篇

猜你喜欢

热点阅读