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

}

 

你可能感兴趣的:(java,spring,spring,java,conditional,bean)