Spring高级装配(二) 条件化的bean
如果你希望一个bean在特定的条件下才会出现:
- 应用的类路径下包含特定的库时才创建
- 只有当某个特定的bean也声明之后才会创建
- 某个特定的环境变量设定之后才创建某个bean
在Spring 4之前,很难实现这种级别的条件化配置,但是Spring4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上。如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。
示例:设置了magic环境属性才去实例化MagicBean
@Bean
@Conditional(MagicExistsCondition.class) // 条件化地创建bean
public MagicBean magicBean() {
return new MagicBean();
}
这里的@Conditional中给定了一个Class,它指明了条件,也就是MagicCondition。
Condition接口如下:
public interface Condition {
boolean matches(ConditionContext ctxt, AnnotatedTypeMetadata metadata);
}
设置给@Conditional的类可以使任意实现了Condition接口的类型。如此一来,只需要提供matches( )方法的实现即可。如果matches( )方法返回为true,那么就会创建带有@Conditional注解的bean。反之则不会创建这些bean。
MagicExistsCondition的实现:
public class MagicExistsCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
return env.containsProperty("magic"); // 检查是否有magic属性
}
}
上面的例子中只获取了Environment,ConditionContext中的内容还挺丰富的,它是一个接口:
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
通过ConditionContext,可以拿到的资源有:
- 借助getRegistry()返回的BeanDefinitionRegistry检查bean的定义
- 借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在(这个屌),甚至探查bean的属性
- 借助getEnvironment()返回的Environment检查环境变量是否存在已经它的值是什么
- 读取并探查getResourceLoader()返回的ResourceLoader所加载的资源
- 借助getClassLoader()返回的ClassLoader加载并检查类是否存在
AnnotationedTypeMetadata则能够让我们检查带有@Bean注解的方法上还有什么其他注解。
public interface AnnotatedTypeMetadata {
boolean isAnnotated(String var1);
Map<String, Object> getAnnotationAttributes(String var1);
Map<String, Object> getAnnotationAttributes(String var1, boolean var2);
MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);
MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
}
通过isAnnotated方法,我们能够判断带有@Bean注解的方法是不是还有其他特定的注解。借助其他的方法,能够检查@Bean注解的方法上其他注解的属性。
在Spring 4开始,@Profile注解进行了重构,使其基于@Conditional和Condition的实现。
在Spring 4中@Profile的实现如下:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();
}
ProfileCondition:
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
return true;
}
}
ProfileCondition通过AnnotatedTypeMetadata得到了用于@Profile注解的所有属性。借助该信息,它会明确地检查value属性,该属性包含了bean的profile名称。然后根据ConditionContext得到的Environment来检查(借助acceptsProfiles()方法)该profile是否处于激活状态。
总结
- @Conditional注解可以实现一个bean的条件化声明
- Profile在Spring 4中使用@Conditional进行了重构
- 实现条件化配置中有两个关键的接口:ConditionContext和AnnotatedTypeMetadata,在检测条件的时候起了关键作用
- 这里没有讲在xml中如何实现条件化配置
- 这里发现用Java来进行config还是挺爽的
Spring高级装配(二) 条件化的bean的更多相关文章
- (二)spring 高级装配-Condition -条件化的bean
Condition:满足某个特定条件的情况下创建bean 条件化配置bean: a:@Conditional 指定一个class ,它指明了通过条件对比的类.如果没有指定class则通过Condito ...
- Spring入门(六):条件化的bean
1. 概念 默认情况下,Spring中定义的bean在应用程序启动时会全部装配,不管当前运行的是哪个环境(Dev,QA或者Prod),也不管当前运行的是什么系统(Windows或者Linux),但有些 ...
- Spring 梳理-profile与条件化定义bean
定义profile <beans> //root <beans profile="dev"> <bean id=.../> </beans ...
- 第3章—高级装配—条件化的Bean
条件化的Bean 通过活动的profile,我们可以获得不同的Bean.Spring 4提供了一个更通用的基于条件的Bean的创建方式,即使用@Conditional注解. @Conditional根 ...
- Spring高级装配bean
目录 spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 一.环境与profile 配置profile bean 在软件开发的时候,有一个 ...
- Spring高级装配
Spring高级装配 目录 一.Profile(根据开发环境创建对应的bean) 二.条件化的创建bean(根据条件创建bean) 三.处理自动装配歧义性(指定首选bean.限定符限制bean) 四. ...
- Spring高级装配(一) profile
Spring高级装配要学习的内容包括: Spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 以上属于高级一点的bean装配技术,如果你没有啥 ...
- 【Java Web开发学习】Spring4条件化的bean
[Java Web开发学习]Spring4条件化的bean 转载:https://www.cnblogs.com/yangchongxing/p/9071960.html Spring4引入了@Con ...
- 002Conditional条件化创建bean
01.条件化配置bean @Bean @Conditional(MagicExistsCondition.class)---->条件化创建bean public MagicBean magicB ...
随机推荐
- 一步一步掌握java的线程机制(二)----Thread的生命周期
之前讲到Thread的创建,那是Thread生命周期的第一步,其后就是通过start()方法来启动Thread,它会执行一些内部的管理工作然后调用Thread的run()方法,此时该Thread就是a ...
- 【转载并整理】Linux - centOS 6 SVN服务器安装、配置及开机启动
以前在windows上安装svn服务器,用的是VisualSVN-Server用起来还不错,但只能用在windows,在linux上部署使用是 subversion,具体说明如下 参考原文:http: ...
- MySQL Metadata Lock详解
Metadata Lock 的作用: 要直接说出Metadata Lock 的作用.以我目前的文字功底是不行的.好在我可以通过一个例子来说明. 假设session 1 在正在执行如下的SQL语句 se ...
- 微信小程序 自定义单选复选按钮组的实现(用于实现购物车产品列表功能)
(一)单选按钮组 模型图如下: index.js Page({ data: { parameter: [{ id: 1, name: '银色' }, { id: 2, name: '白色' },{ i ...
- MySQL数据库优化详解(收藏)
MySQL数据库优化详解 mysql表复制 复制表结构+复制表数据mysql> create table t3 like t1;mysql> insert into t3 select * ...
- 腾讯云服务器 安装fastdfs文件服务器
上篇安装完nginx后,那么这次咱们就来安装fastdfs文件服务器,为何要使用文件服务器,这里不多说了,以前的文章有写过 首先用ftp工具把fastdfs的相关文件上传至腾讯云,如下 首先,安装基本 ...
- iOS缓存-内存缓存
为了减少与服务器的连接沟通次数,提高应用程序的执行速度,使用了iOS的缓存机制 #import "YoungViewController.h" @interface YoungVi ...
- 基于 Promise 的 HTTP 请求客户端 axios
基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用 功能特性 在浏览器中发送 XMLHttpRequests 请求 在 node.js 中发送 http请求 支持 ...
- 《深入应用C++11:代码优化与工程级应用》开始发售
我的新书<深入应用C++11:代码优化与工程级应用>已经开始在华章微店发售了,下面是链接. 京东发售链接 china-pub发售链接 亚马逊发售链接 天猫商城发售链接 适用读者:C++11 ...
- python(41):copy拷贝(深拷贝deepcopy与浅拷贝copy)
Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块. 1.copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2.copy.deepco ...