Spring条件化装配Bean
2017-01-16 | Visit count 1231484
Spring4引入了@Conditional注解,可配合@Bean或者@Component注解一起使用。
用CET4考试来演示@Conditional注解。
新建考试结果Result接口:
1 2 3 |
public interface Result {
public void getResult();
}
|
实现类CET4:
1 2 3 4 5 |
public class CET4 implements Result{
public void getResult() {
System.out.println("恭喜你通过CET4");
}
}
|
定义学生接口:
1 2 3 |
public interface Student {
public void exam();
}
|
实现类XiaoMing:
1 2 3 4 5 6 7 8 9 10 |
public class XiaoMing implements Student{
//注入result
@Autowired(required=false)
private Result result;
public void exam() {
if(result == null) System.out.println("抱歉,CET4未通过");
else result.getResult();
}
}
|
配置JavaConfig:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionConfig {
@Bean
@Conditional(ResultCondition.class)
public Result result(){
return new CET4();
}
@Bean(name="xiaoming")
public Student student(){
return new XiaoMing();
}
}
|
可以看到,@Conditional中给定了一个Class,它指明了条件——在本例中,也就是ResultCondition:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class ResultCondition implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
//获取环境变量中的result属性
String result = env.getProperty("result");
if("success".equals(result)) return true;
else return false;
}
}
|
设置给@Conditional的类可以是任意实现了Condition接口的类型。可以看出来,这个接口实现起来很简单直接,只需提供matches()方法的实现即可。如果matches()方法返回 true,那么就会创建带有@Conditional注解的bean。如果matches()方法返回false,将不会创建这些bean。
ConditionContext是一个接口,大致如下所示:
1 2 3 4 5 6 7 |
public interface conditioncontext{
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
ResourceLoader getResourceLoader();
Environment getEnvironment();
ClassLoder getClassLoader();
}
|
通过ConditionContext,我们可以做到如下几点:
1.借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;
2.借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚至探查bean的属性;
3.借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么;
4.读取并探查getResourceLoader()返回的ResourceLoader所加载的资源;
5.借助getClassLoader()返回的ClassLoader加载并检查类是否存在。
AnnotatedTypeMetadata则能够让我们检查带有@Bean注解的方法上还有什么其他的注解。像ConditionContext一样,AnnotatedTypeMetadata也是一个接口。它如下所示:
1 2 3 4 5 6 7 8 9 10 |
public interface AnnotatedTypeMetadata{
boolean isAnnotated(String annotationType);
Map<String,Object> getAnnotationAttributes(String annotationType);
Map<String,Object> getAnnotationAttributes(
String annotationType,boolean classValuesAsString);
MutilValueMap<String,Object> getAllAnnotationAttributes(
String annotationType);
MutilValueMap<String,Object> getAllAnnotationAttributes(
String annotationType,boolean classValuesAsString);
}
|
借助isAnnotated()方法,我们能够判断带有@Bean注解的方法是不是还有其他特定的注解。借助其他的那些方法,我们能够检查@Bean注解的方法上其他注解的属性。
现在测试@Conditional注解的作用:
1 2 3 4 5 6 7 8 |
public class TestConditional {
public static void main(String[] args) {
System.setProperty("result", "fail");
ApplicationContext ac = new AnnotationConfigApplicationContext(ConditionConfig.class);
Student xiaoming = (Student) ac.getBean("xiaoming");
xiaoming.exam();
}
}
|
这里设置result为fail,ResultCondition的matches()方法返回false,所以CET4 Bean并不会被创建,结果应该输出“抱歉,CET4未通过”,测试结果:
1 |
抱歉,CET4未通过 |
Spring条件化装配Bean详解
1437

被折叠的 条评论
为什么被折叠?



