学习了profile bean之后,发现有的时候bean还是有根据环境来选择的余地的,那么假设我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建。我们还可能要求只有某个特定的环境变量设置之后,才会创建某个bean。

在Spring 4之前,很难实现这种级别的条件化配置,但是Spring 4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。

今天就来学习下 条件化的Bean。

创建方法是在方或者类上 添加一个@Conditional(xxx.class)  xxx.class表示一个逻辑性的内容,当满足需求的时候返回true这样一来这个@Bean就会被创建,反之就不创建

 @Bean
@Conditional(XXX.class)

这样一来,跟profile还是有点相似的,但是比他要强大的多的多。。。我们看Profile源码,你会发现Profile也添加了@Conditional,代码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();
}

这个时候在查看下ProfileCondition.class

class ProfileCondition implements Condition {
ProfileCondition() {
}
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if(context.getEnvironment() != null) {
MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if(attrs != null) {
Iterator var4 = ((List)attrs.get("value")).iterator();
Object value;
do {
if(!var4.hasNext()) {
return false;
}
value = var4.next();
} while(!context.getEnvironment().acceptsProfiles((String[])((String[])value))); return true;
}
}
return true;
}
}

这个时候我们会发现 有一个接口 Condition,之所以那么牛逼 估计全靠这个吧,看一下源码:

public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

有了ConditionContext,我们可以做到如下几点:

  • 借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;
  • 借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是
  • 否存在,甚至探查bean的属性;
  • 借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是
  • 什么;
  • 读取并探查getResourceLoader()返回的ResourceLoader所加载的资源;
  • 借助getClassLoader()返回的ClassLoader加载并检查类是否存在。

有了AnnotatedTypeMetadata则能够让我们检查带有@Bean注解的方法上还有什么其他的注解。

下面就以例子来说明:

假设有两个赏金猎人,一个高级的,一个初级的,他们各种会根据各自的赏金面板的消息(即Condition接口的实现类),决定是否去开始猎杀目标,下面先创造猎人接口以及两个猎人

public interface BountyHunter {

    void BeginHuntAndKill();
}

高级赏金猎人

public class SeniorBountyHunter implements BountyHunter {

    public void BeginHuntAndKill() {
System.out.println("我是高级赏金猎人哇哈哈哈,现在已有任务发布,我可以去做任务了!");
}
}

初级赏金猎人

public class PrimaryBountyHunter implements BountyHunter {

    public void BeginHuntAndKill() {
System.out.println("我是初级赏金猎人乌卡卡卡,现在已有任务发布,我可以去做任务了!");
}
}

然后分别再创建 各自的任务面板

高级任务

public class SeniorBounty implements Condition {

    public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
/**
* 各种自己想要的验证,然后根据结果来返回 一个boole值
*/
if (conditionContext.getEnvironment().acceptsProfiles("task")) {
return true;
} else {
return false;
}
}
}

初级任务

public class PrimaryBounty implements Condition {

    public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
/**
* 各种自己想要的验证,然后根据结果来返回 一个boole值
*/ if (conditionContext.getEnvironment().acceptsProfiles("task")) {
return true;
} else {
return false;
}
}
}

任务有了,人物也有了,下面就是需要一个人大喊一下:有新的任务发布了,赶紧去看啊!!

也就是Bean配置类

@Configuration
public class TaskConfig { @Bean
@Conditional(PrimaryBounty.class)
public BountyHunter ThePrimaryBountyHunter() {
return new PrimaryBountyHunter();
} @Bean
@Conditional(SeniorBounty.class)
public BountyHunter TheSeniorBountyHunter() {
return new SeniorBountyHunter();
}
}

现在有人通知了,让我们看一下是否有人领任务,开始去猎杀!

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TaskConfig.class)
@ActiveProfiles("task")
public class TaskBegin { @Autowired
SeniorBountyHunter seniorBountyHunter; @Autowired
PrimaryBountyHunter primaryBountyHunter; @Test
public void TaskLog() {
if (primaryBountyHunter != null) {
primaryBountyHunter.BeginHuntAndKill();
}
if (seniorBountyHunter != null) {
seniorBountyHunter.BeginHuntAndKill();
}
}
}

这边我们是根据Profile来测试的,根据这个判断任务是否满足,当然我们也可以不根据配置环境,我们可以根据任务的的属性是否跟猎人相匹配(即 可以根据 @Conditional(xxx.class) xxx.class 类中的判断,该Bean是否有我们需要的属性 )

测试结果

以上就是条件化的bean配置 简单小例子,如有错误,请指出,谢谢~

代码:https://github.com/eoooxy/springinaction test下 的com.bean.condition中

SpringInAction--条件化的Bean的更多相关文章

  1. 第3章—高级装配—条件化的Bean

    条件化的Bean 通过活动的profile,我们可以获得不同的Bean.Spring 4提供了一个更通用的基于条件的Bean的创建方式,即使用@Conditional注解. @Conditional根 ...

  2. 002Conditional条件化创建bean

    01.条件化配置bean @Bean @Conditional(MagicExistsCondition.class)---->条件化创建bean public MagicBean magicB ...

  3. Spring入门(六):条件化的bean

    1. 概念 默认情况下,Spring中定义的bean在应用程序启动时会全部装配,不管当前运行的是哪个环境(Dev,QA或者Prod),也不管当前运行的是什么系统(Windows或者Linux),但有些 ...

  4. (二)spring 高级装配-Condition -条件化的bean

    Condition:满足某个特定条件的情况下创建bean 条件化配置bean: a:@Conditional 指定一个class ,它指明了通过条件对比的类.如果没有指定class则通过Condito ...

  5. Spring 梳理-profile与条件化定义bean

    定义profile <beans> //root <beans profile="dev"> <bean id=.../> </beans ...

  6. 【Java Web开发学习】Spring4条件化的bean

    [Java Web开发学习]Spring4条件化的bean 转载:https://www.cnblogs.com/yangchongxing/p/9071960.html Spring4引入了@Con ...

  7. Spring高级装配(二) 条件化的bean

    如果你希望一个bean在特定的条件下才会出现: 应用的类路径下包含特定的库时才创建 只有当某个特定的bean也声明之后才会创建 某个特定的环境变量设定之后才创建某个bean 在Spring 4之前,很 ...

  8. 001profile条件化创建bean

    01.类级别条件创建 @Configuration @Profile("dev") public class Aclass{}---->影响整个类,包括类的注解.开发环境,类 ...

  9. @Condition 条件化注册Bean

    看<Spring源码深度解析>笔记 1.@Condition: 按照一定的条件进行判断,满足条件给容器中注册bean:实例: 根据系统给容器中注册Bean,如果是windows注册(“bi ...

  10. spring对bean的高级装配之基于@Conditional条件化装配

    上篇介绍了如何基于profile来条件化创建bean,spring会根据profile的激活状态来进行创建;这篇介绍如何基于spring4.0引入的@Conditional和Condition接口来更 ...

随机推荐

  1. 测试应用documentFragment 和 直接操作dom 的区别

    DocumentFragment 节点不属于文档树,继承的 parentNode 属性总是 null. 不过它有一种特殊的行为,该行为使得它非常有用,即当请求把一个 DocumentFragment ...

  2. ORA-00257: archiver error的解决方法

    背景:多个用户同时做测试数据,有时候突然Oracle系统就崩溃了,然后报一个ORA-00257: archiver error. Connect internal only, until freed的 ...

  3. 详解Java中的clone方法 -- 原型模式

    转自: http://blog.csdn.net/zhangjg_blog/article/details/18369201 Java中对象的创建   clone顾名思义就是复制, 在Java语言中, ...

  4. 【DeepLearning学习笔记】Neurons神经元

    今天找到一个比较好的deep learning的教材:Neural Networks and Deep Learning 对神经网络有详细的讲解,鉴于自己青年痴呆,还是总结下笔记吧=.= Percep ...

  5. JCenter下载太慢?教你修改Maven仓库地址为国内镜像

    http://blog.csdn.net/biezhihua/article/details/49668605 转载自:http://www.yrom.net/blog/2015/02/07/chan ...

  6. 线代笔记 #01# 几何水平上的理解 VS. 数值水平上的理解

    源: 线性代数的本质 内容来自字幕. Let me quote without further comment from Dieudonné's "Foundations of Modern ...

  7. Django学习笔记之利用Form和Ajax实现注册功能

    一.注册相关的知识点 1.Form组件 我们一般写Form的时候都是把它写在views视图里面,那么他和我们的视图函数也不影响,我们可以吧它单另拿出来,在应用下面建一个forms.py的文件来存放 2 ...

  8. 关于MVC 中EF调用存储过程

    Entity Framework 4.3 中使用存储过程 分类:ASP.NET MVC 3, ASP.NET                  0                   尽管 Entit ...

  9. linux字典生成工具crunch

    安装 tar zxvf crunch-3.6.tgz cd crunch-3.6 gcc -Wall -lm -pthread -std=c99 -m64 -D_LARGEFILE_SOURCE -D ...

  10. 梅森素数应用 nefu 120

    梅森素数 定义: if m是一个正整数 and 2^m-1是一个素数 then m是素数 if m是一个正整数 and m是一个素数 then M(m)=2^m-1被称为第m个梅森数 if p是一个素 ...