SpringInAction--条件化的Bean
学习了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的更多相关文章
- 第3章—高级装配—条件化的Bean
条件化的Bean 通过活动的profile,我们可以获得不同的Bean.Spring 4提供了一个更通用的基于条件的Bean的创建方式,即使用@Conditional注解. @Conditional根 ...
- 002Conditional条件化创建bean
01.条件化配置bean @Bean @Conditional(MagicExistsCondition.class)---->条件化创建bean public MagicBean magicB ...
- Spring入门(六):条件化的bean
1. 概念 默认情况下,Spring中定义的bean在应用程序启动时会全部装配,不管当前运行的是哪个环境(Dev,QA或者Prod),也不管当前运行的是什么系统(Windows或者Linux),但有些 ...
- (二)spring 高级装配-Condition -条件化的bean
Condition:满足某个特定条件的情况下创建bean 条件化配置bean: a:@Conditional 指定一个class ,它指明了通过条件对比的类.如果没有指定class则通过Condito ...
- Spring 梳理-profile与条件化定义bean
定义profile <beans> //root <beans profile="dev"> <bean id=.../> </beans ...
- 【Java Web开发学习】Spring4条件化的bean
[Java Web开发学习]Spring4条件化的bean 转载:https://www.cnblogs.com/yangchongxing/p/9071960.html Spring4引入了@Con ...
- Spring高级装配(二) 条件化的bean
如果你希望一个bean在特定的条件下才会出现: 应用的类路径下包含特定的库时才创建 只有当某个特定的bean也声明之后才会创建 某个特定的环境变量设定之后才创建某个bean 在Spring 4之前,很 ...
- 001profile条件化创建bean
01.类级别条件创建 @Configuration @Profile("dev") public class Aclass{}---->影响整个类,包括类的注解.开发环境,类 ...
- @Condition 条件化注册Bean
看<Spring源码深度解析>笔记 1.@Condition: 按照一定的条件进行判断,满足条件给容器中注册bean:实例: 根据系统给容器中注册Bean,如果是windows注册(“bi ...
- spring对bean的高级装配之基于@Conditional条件化装配
上篇介绍了如何基于profile来条件化创建bean,spring会根据profile的激活状态来进行创建;这篇介绍如何基于spring4.0引入的@Conditional和Condition接口来更 ...
随机推荐
- vux在ISO中异常 this.$vux.confirm.show
在按钮事件中调用this.$vux.confirm.show,并且启用按钮的show-loading属性 安卓正常,ios中弹窗无法显示 经过排查,iso中设置按钮的loading后,要用异步setT ...
- Cloudera Manager安装之时间服务器和时间客户端(二)
福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 Java全栈大联盟 ...
- Spark机器学习9· 实时机器学习(scala with sbt)
1 在线学习 模型随着接收的新消息,不断更新自己:而不是像离线训练一次次重新训练. 2 Spark Streaming 离散化流(DStream) 输入源:Akka actors.消息队列.Flume ...
- centos7 安装 gitolite (git服务器)
gitolite简介 轻量级git服务器程序,解决了git权限管理的问题.(git是一个分布式版本控制系统,就是说每个人作为客户端的同时又是服务器)项目GitHub地址:https://github. ...
- hive + hadoop 环境搭建
机器规划: 主机 ip 进程 hadoop1 10.183.225.158 hive server hadoop2 10.183.225.166 hive client 前置条建: kerberos部 ...
- 在linux环境下安装python3.6
wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz --no-check-certificat gunzip Python-3. ...
- obtainBuffer timed out (is the CPU pegged?)
https://stackoverflow.com/questions/5293025/audiotrack-lag-obtainbuffer-timed-out [典] 03-13 14:55:57 ...
- linux网络连接的查看和端口的监听
网络软件都是由客户端和服务端组成,由服务端在服务器上监听指定的端口处理接收到的数据,而客户端是向服务器端监听的端口发送数据,并由服务器端对该数据进行处理,然后将处理结果返回给客户端. 那么我们在lin ...
- 数据库还原,System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权。 (Microsoft.SqlServer.SmoExtended)
数据库还原问题: System.Data.SqlClient.SqlError: 因为数据库正在使用,所以无法获得对数据库的独占访问权. (Microsoft.SqlServer.SmoExtende ...
- 如何更改nagios监控默认的检查时间
/usr/local/nagios/etc/nagios.cfg: interval_length 表示时间单位,默认为60,即1分钟 /usr/local/nagios/etc/objects/se ...