当前位置:网站首页>Spirng @Conditional 条件注解的使用
Spirng @Conditional 条件注解的使用
2022-07-25 11:45:00 【丑基地】
1、简介
@Conditional 是 Spring 4.0 提出的一个新的注解,当标注的对象满足所有的条件时,才能注册为 Spring 中的 bean。
@Conditional 源码中的定义如下:
@Target({
ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
可以看到 @Conditional 可以使用在类上或者方法上。具体使用方式如下:
1、 在标注或元标注了 @Component 组件的类上进行标注;
2、作为元注解直接标注在其他注解上面;
3、在标注了 @Bean 注解的方法上标注。
@Conditional 注解有一个 value 属性,其值只能为 Condition 类型的数组,使用 @Conditional 时必须进行指定(多个 Condition 是与的关系,多个条件需要都满足。默认按照定义的顺序指定,可以通过 @Order 对Condition 进行排序)。
Condition 是指具体的条件,是一个接口,需要自己实现。
@FunctionalInterface
public interface Condition {
/** * 确定条件是否匹配 */
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
Condition 是一个函数式接口,只有一个 matches 方法,返回 true 表示 Component 可以注册为 Spring 中的 bean。有两个参数:
1、 ConditionContext:表示条件的上下文信息;
public interface ConditionContext {
/** * 获取持有 BeanDefinition 的注册中心,BeanDefinition 是 Spring bean 的定义,BeanDefinitionRegistry 可以用来注册或查找 BeanDefinition。 */
BeanDefinitionRegistry getRegistry();
/** * 获取 BeanFactory,BeanFactory 是 spring 最基础的容器,保存有 spring 的 bean 实例 */
@Nullable
ConfigurableListableBeanFactory getBeanFactory();
/** * 获取当前应用运行的环境信息 */
Environment getEnvironment();
/** * 获取当前使用的 ResourceLoader,其可以用来加载各种各样的资源 */
ResourceLoader getResourceLoader();
/** * 获取加载其他类的 ClassLoader */
@Nullable
ClassLoader getClassLoader();
}
2、 AnnotatedTypeMetadata:表示类或方法上的注解元信息。
public interface AnnotatedTypeMetadata {
/** * 返回直接标注的注解详情 * @since 5.2 */
MergedAnnotations getAnnotations();
/** * 确定元素是否具有给定类型定义的注解或元注解 */
default boolean isAnnotated(String annotationName) {
return getAnnotations().isPresent(annotationName);
}
/** * 获取给定类型的注解属性,考虑属性重写 */
@Nullable
default Map<String, Object> getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false);
}
/** * 获取给定类型的注解属性,考虑属性重写 */
@Nullable
default Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
MergedAnnotation<Annotation> annotation = getAnnotations().get(annotationName, null, MergedAnnotationSelectors.firstDirectlyDeclared());
if (!annotation.isPresent()) {
return null;
}
return annotation.asAnnotationAttributes(Adapt.values(classValuesAsString, true));
}
/** * 获取给定类型的所有注解的所有属性,不考虑属性重写 */
@Nullable
default MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
/** * 获取给定类型的所有注解的所有属性,不考虑属性重写 */
@Nullable
default MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
Adapt[] adaptations = Adapt.values(classValuesAsString, true);
return getAnnotations().stream(annotationName)
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getMetaTypes))
.map(MergedAnnotation::withNonMergedAttributes)
.collect(MergedAnnotationCollectors.toMultiValueMap(map -> map.isEmpty() ? null : map, adaptations));
}
}
2、实战
要实现的目标:根据不同的环境,配置不同的线程池。步骤如下:
1、自定义 Condition,匹配条件:
/** * @Des 匹配本地开发环境 * @Author jidi * @Email [email protected] * @Date 2022/7/23 */
public class ProfilesActiveOfDevCondition implements Condition {
private static final String DEV = "dev";
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 获取配置属性 spring.profiles.active
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("spring.profiles.active");
return Objects.equals(DEV, property);
}
}
/** * @Des 匹配生产环境 * @Author jidi * @Email [email protected] * @Date 2022/7/23 */
public class ProfilesActiveOfProCondition implements Condition {
private static final String PRO = "pro";
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 获取配置属性 spring.profiles.active
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("spring.profiles.active");
return Objects.equals(PRO, property);
}
}
2、定义具体的线程池,通过 @Conditional 注解指定各自生效的环境:
/** * @Des * @Author jidi * @Email [email protected] * @Date 2022/7/23 */
@Configuration
@Slf4j
public class ApplicationConfig {
/** * 开发环境 */
@Bean
@Conditional(value = {
ProfilesActiveOfDevCondition.class})
public ThreadPoolExecutor devExecutor(){
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
5,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy());
// 预先初始化所有核心线程
executor.prestartAllCoreThreads();
log.info("初始化开发环境线程池!");
return executor;
}
/** * 生产环境 */
@Bean
@Conditional(value = {
ProfilesActiveOfProCondition.class})
public ThreadPoolExecutor proExecutor(){
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
20,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1024),
new ThreadPoolExecutor.CallerRunsPolicy());
// 预先初始化所有核心线程
executor.prestartAllCoreThreads();
log.info("初始化生产环境线程池!");
return executor;
}
}
3、在配置文件中配置属性 spring.profiles.active,启动工程,即可根据不同的配置加载不同的线程池。
3、其他 @Conditional 扩展注解
除了 @Conditional 注解外,Spring 还内置了很多其他的条件注解,并且已经实现了它们的匹配逻辑,可以直接使。主要有以下注解:
1、@ConditionalOnBean:当Spring容器内存在指定Bean时生效;
2、@ConditionalOnMissingBean:当Spring容器内不存在指定Bean时生效;
3、@ConditionalOnClass:当Spring容器内存在指定Class时生效;
4、@ConditionalOnMissingClass:当Spring容器内不存在指定Class时生效;
5、@ConditionalOnProperty:当指定的属性满足匹配条件时生效;
6、@ConditionalOnResource:当类路径下有指定资源时生效;
7、@ConditionalOnWebApplication:当项目为web项目时生效;
8、@ConditionalOnNotWebApplication:当项目不为web项目时生效;
9、@ConditionalOnExpression:当SpEL表达式成立时生效;
10、@ConditionalOnJava:当满足JVM版本时生效;
11、@ConditionalOnJndi:当指定JNDI存在时生效。
边栏推荐
猜你喜欢

NLP的基本概念1

客户端开放下载, 欢迎尝鲜

PyTorch项目实战—FashionMNIST时装分类

嵌套事务 UnexpectedRollbackException 分析与事务传播策略

Build a series of vision transformer practices, and finally meet, Timm library!

Location analysis of recording an online deadlock

从云原生到智能化,深度解读行业首个「视频直播技术最佳实践图谱」

Video caption (cross modal video summary / subtitle generation)

Add a little surprise to life and be a prototype designer of creative life -- sharing with X contestants in the programming challenge

Eureka usage record
随机推荐
WPF project introduction 1 - Design and development of simple login page
【8】 Clever use of color finder
Experimental reproduction of image classification (reasoning only) based on caffe resnet-50 network
嵌套事务 UnexpectedRollbackException 分析与事务传播策略
Pytorch environment configuration and basic knowledge
R语言使用wilcox.test函数执行wilcox符号秩检验获取总体中位数(median)的置信区间(默认输出结果包括95%置信水平的置信区间)
给生活加点惊喜,做创意生活的原型设计师丨编程挑战赛 x 选手分享
Can't delete the blank page in word? How to operate?
Word中的空白页,怎么也删不掉?如何操作?
循环创建目录与子目录
Introduction to the scratch crawler framework
Hydrogen entrepreneurship competition | Liu Yafang, deputy director of the science and Technology Department of the National Energy Administration: building a high-quality innovation system is the cor
基于Caffe ResNet-50网络实现图片分类(仅推理)的实验复现
【3】 DEM mountain shadow effect
MySQL exercise 2
第一个scrapy爬虫
【Flutter -- 实例】案例一:基础组件 & 布局组件综合实例
cmake 学习使用笔记(二)库的生成与使用
【高并发】通过源码深度分析线程池中Worker线程的执行流程
Pytorch advanced training skills