Spring系列第20篇:@Conditional通过条件来控制bean的注册

ConfigurationCondition接口相对于Condition接口多了一个getConfigurationPhase方法,用来指定条件判断的阶段,是在解析配置类的时候过滤还是在创建bean的时候过滤。

@Conditional使用的3步骤


  1. 自定义一个类,实现Condition或ConfigurationCondition接口,实现matches方法

  2. 在目标对象上使用@Conditional注解,并指定value的指为自定义的Condition类型

  3. 启动spring容器加载资源,此时@Conditional就会起作用了

案例1:阻止配置类的处理


在配置类上面使用@Conditional,这个注解的value指定的Condition当有一个为false的时候,spring就会跳过处理这个配置类。

自定义一个Condition类:

package com.javacode2018.lesson001.demo25.test3;

import org.springframework.context.annotation.Condition;

import org.springframework.context.annotation.ConditionContext;

import org.springframework.core.type.AnnotatedTypeMetadata;

public class MyCondition1 implements Condition {

@Override

public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

return false;

}

}

matches方法内部我们可以随意发挥,此处为了演示效果就直接返回false。

来个配置类,在配置类上面使用上面这个条件,此时会让配置类失效,如下:

package com.javacode2018.lesson001.demo25.test3;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Conditional;

import org.springframework.context.annotation.Configuration;

@Conditional(MyCondition1.class) //@1

@Configuration

public class MainConfig3 {

@Bean

public String name() { //@1

return “路人甲Java”;

}

}

@1:使用了自定义的条件类

@2:通过@Bean标注这name这个方法,如果这个配置类成功解析,会将name方法的返回值作为bean注册到spring容器

来个测试类,启动spring容器加载MainConfig3配置类,如下:

package com.javacode2018.lesson001.demo25;

import com.javacode2018.lesson001.demo25.test3.MainConfig3;

import org.junit.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Map;

public class ConditionTest {

@Test

public void test3() {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig3.class);

Map<String, String> serviceMap = context.getBeansOfType(String.class);

serviceMap.forEach((beanName, bean) -> {

System.out.println(String.format(“%s->%s”, beanName, bean));

});

}

}

test3中,从容器中获取String类型的bean,运行test3没有任何输出。

我们可以将MainConfig3上面的@Conditional去掉,再次运行输出:

name->路人甲Java

案例2:阻止bean的注册


来个配置类,如下:

package com.javacode2018.lesson001.demo25.test4;

import com.javacode2018.lesson001.demo25.test3.MyCondition1;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Conditional;

import org.springframework.context.annotation.Configuration;

@Configuration

public class MainConfig4 {

@Conditional(MyCondition1.class) //@1

@Bean

public String name() {

return “路人甲Java”;

}

@Bean

public String address() {

return “上海市”;

}

}

上面2个方法上面使用了@Bean注解来定义了2个bean,name方法上面使用了@Conditional注解,这个条件会在name这个bean注册到容器之前会进行判断,当条件为true的时候,name这个bean才会被注册到容器。

ConditionTest中新增个测试用例来加载上面这个配置类,从容器中获取String类型所有bean输出,代码如下:

@Test

public void test4() {

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig4.class);

Map<String, String> serviceMap = context.getBeansOfType(String.class);

serviceMap.forEach((beanName, bean) -> {

System.out.println(String.format(“%s->%s”, beanName, bean));

});

}

运行输出:

address->上海市

可以看到容器中只有一个address被注册了,而name这个bean没有被注册。

案例3:bean不存在的时候才注册


需求

IService接口有两个实现类Service1和Service1,这两个类会放在2个配置类中通过@Bean的方式来注册到容器,此时我们想加个限制,只允许有一个IService类型的bean被注册到容器。

可以在@Bean标注的2个方法上面加上条件限制,当容器中不存在IService类型的bean时,才将这个方法定义的bean注册到容器,下面来看代码实现。

代码实现

条件判断类:OnMissingBeanCondition

package com.javacode2018.lesson001.demo25.test1;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import org.springframework.context.annotation.Condition;

import org.springf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值