Spring 自定义 CustomQualifier

为什么写这篇文章

        Spring 支持类型注入,并且可以通过Qualifier 或者Mate 调整类型注入的范围。但是通过自定义注解结合现有的 @Qualifier 使用起来有种种困难。

  • 将 @Qualifier 融合在自定义注解中,在使用 @AliasFor 遇到问题
  • 仅仅检查注解中的一部分内容是否匹配即可,Spring 不支持

添加自定义 Qualifier

package ann;import java.lang.annotation.*;/*** @author Jay*/
@Target({ElementType.PARAMETER,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HandlerSelect {String value() default "";
}

组合 Qualifier 注解

package ann;import java.lang.annotation.*;/*** @author Jay*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MessageHandlerAnn {HandlerSelect qualifier();/*** 通过SpEL 表达式计算 #messageExt 的相关信息是否满足所有条件** @return*/String[] eLFilter() default "";}

注册自定义限定符

    @Beanpublic CustomAutowireConfigurer customAutowireConfigurer() {CustomAutowireConfigurer configurer = new CustomAutowireConfigurer();configurer.setCustomQualifierTypes(Collections.singleton(HandlerSelect.class));return configurer;}

自定义注解处理工厂处理器

package config;import ann.HandlerSelect;
import ann.MessageHandlerAnn;
import message.handler.MessageHandler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.stereotype.Component;/*** @author Jay*/
@Component
public class HandlerSelectQualifierProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 检查 实现了 MessageHandler 接口的 SpringBean 检查其是否标注有 MessageHandlerAnn 注解String[] beanNamesForType = beanFactory.getBeanNamesForType(MessageHandler.class);for (String beanName : beanNamesForType) {// 获取 Bean 定义对象BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);Class<?> beanClass = beanFactory.getType(beanName);// 检查是否有 MessageHandlerAnn 注解if (beanClass != null && beanClass.isAnnotationPresent(MessageHandlerAnn.class)) {// 创建并添加自定义的 qualifier 元素addCustomQualifier((AbstractBeanDefinition) beanDefinition, beanClass);}}}private static void addCustomQualifier(AbstractBeanDefinition beanDefinition, Class<?> beanClass) {// 创建 AutowireCandidateQualifier 实例(HandlerSelect 已经加入到 QualifierType 中)AutowireCandidateQualifier qualifier = new  AutowireCandidateQualifier(HandlerSelect.class);// 设置 qualifier 的值,例如:HandlerSelect qualifierValue = beanClass.getAnnotation(MessageHandlerAnn.class).qualifier();//  Attribute 的 Key 固定为 value, 其 value 值取自 HandlerSelect.qualifier.valuequalifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, qualifierValue.value());// TODO 以上处理仅考虑 HandlerSelect 仅仅有一个限定描述符的场景。 如果需要拓展 HandlerSelect  的属性, 需要重新设计以上代码     // 添加限定符beanDefinition.addQualifier(qualifier);}
}

 MyMessageListener & MessageHandler

public interface MessageHandler {}public class MyMessageListener implements MessageListenerConcurrently, InitializingBean {final private List<MessageHandler<?>> messageHandlerList;public MyMessageListener(List<MessageHandler<?>> messageHandlerList) {this.messageHandlerList = messageHandlerList;}public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {for (MessageExt messageExt : msgs) {// ...}}@Overridepublic void afterPropertiesSet() {System.out.println("MyMessageListener afterPropertiesSet");// messageHandlerList 不能为空if (ObjectUtils.isEmpty(this.messageHandlerList)) {log.error("messageHandlerList is empty");throw new RuntimeException("messageHandlerList is empty");} else {messageHandlerList.forEach(messageHandler -> {System.out.println(messageHandler.getClass().getName());});}}
}

配置&效果

待完善的地方 

  • 用于解析 @HandlerSelect 的 HandlerSelectQualifierProcessor 不能随着 HandlerSelect 的属性增加而 解析属性并增加对应的限定符
  • IDEA 工具无法预估 使用自定义的限定符号 还有哪些Bean

(截图红框显示为三个, 但实际myMessageListener0 依赖注入了T0T0、ToT1 而myMessageListener1 依赖注入了T1T0 )

相关博客: rocketmq Listener 还可以这样配置(基于SPEL\限定符号\自动连线)icon-default.png?t=N7T8http://t.csdnimg.cn/sE1Dk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/287768.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外包干了10天,技术倒退明显

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

Tomcat下载安装以及配置

一、Tomcat介绍 二、Tomcat下载安装 进入tomcat官网&#xff0c;https://tomcat.apache.org/ 1、选择需要下载的版本&#xff0c;点击下载 下载路径一定要记住&#xff0c;并且路径中尽量不要有中文 8、9、10都可以&#xff0c;本博文以8为例 2、将下载后的安装包解压到指定位…

【小黑送书—第十四期】>>重磅升级——《Excel函数与公式应用大全》(文末送书)

今天给大家带来AI时代系列书籍&#xff1a;《Excel 2019函数与公式应用大全》全新升级版&#xff0c;Excel Home多位微软全球MVP专家打造&#xff0c;精选Excel Home海量案例&#xff0c;披露Excel专家多年研究成果&#xff0c;让你分分钟搞定海量数据运算&#xff01; 由北京…

YOLOv8官方仓库正式支持RT-DETR训练、测试以及推理

YOLOv8太卷啦 | YOLOv8官方仓库正式支持RT-DETR训练、测试以及推理 RT-DETR由百度开发&#xff0c;是一款端到端目标检测器&#xff0c;在保持高精度的同时提供实时性能。它利用ViT的强大特性&#xff0c;通过解耦尺度内交互和跨尺度融合来有效处理多尺度特征。 RT-DETR具有很强…

关闭Elasticsearch built-in security features are not enabled

禁用Kibana安全提示&#xff08;Elasticsearch built-in security features are not enabled&#xff09; Kibana提示#! Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.e…

C语言中位运算介绍

在C语言中&#xff0c;位运算是一种对二进制位进行操作的运算方式&#xff0c;它可以对数据的二进制表示进行位级别的操作&#xff0c;包括按位与、按位或、按位异或、按位取反等。位运算常用于处理底层数据结构、优化代码性能以及实现各种算法。本文将深入介绍C语言中的位运算…

spring 的理解

spring 的理解 spring 是一个基础的框架&#xff0c;同时提高了一个Bean 的容器&#xff0c;用来装载Bean对象spring会帮我们创建Bean 对象并维护Bean对象 的生命周期。在spring 框架上&#xff0c;还有springCloud,spring Boot 的技术框架&#xff0c;都是以Spring为基石的sp…

AIGC工具系列之——基于OpenAI的GPT大模型搭建自己的AIGC工具

今天我们来讲讲目前非常火的人工智能话题“AIGC”&#xff0c;以及怎么使用目前的AI技术来开发&#xff0c;构建自己的AIGC工具 什么是AIGC&#xff1f; AIGC它的英文全称为(Artificial Intelligence Generated Content)&#xff0c;中文翻译过来就是“人工智能生成内容”&…

HDFSRPC通信框架详解

本文主要对HDFSRPC通信框架解析。包括listener&#xff0c;reader&#xff0c;handler&#xff0c;responser等实现类的源码分析。注意hadoop版本为3.1.1。 写在前面 rpc肯定依赖于socket通信&#xff0c;并且使用的是java NIO。读者最好对nio有一定的了解&#xff0c;文章中…

《量子计算:揭开未来科技新篇章》

随着科技的不断发展&#xff0c;量子计算作为一项颠覆性的技术逐渐走进人们的视野&#xff0c;引发了广泛的关注和探讨。本文将围绕量子计算的技术进展、技术原理、行业应用案例、未来趋势预测以及学习路线等方向&#xff0c;深入探讨这一领域的前沿动态和未来发展趋势。 量子…

极端道路天气数据集 雨天 雾天 道路晴朗

极端道路天气数据集 是一系列专为自动驾驶、智能交通系统研发以及计算机视觉算法测试而设计的真实世界或模拟的道路环境图像和视频集合。这些数据集包含了在各类极端天气条件下捕捉到的道路场景&#xff0c;例如大雾、暴雨、暴雪、冰雹、雾霾、道路结冰等&#xff0c;这些都是…

移动硬盘未初始化?数据恢复指南助你轻松应对

当我们插上移动硬盘准备使用时&#xff0c;却发现电脑提示“移动硬盘未初始化”&#xff0c;这无疑会让我们感到困扰和焦虑。毕竟&#xff0c;硬盘中可能存储着重要的文件、照片、视频等个人或工作资料。那么&#xff0c;面对移动硬盘未初始化的问题&#xff0c;我们该如何应对…

管理能力学习笔记三:管理者的时间管理法

时间管理三步法 1、对任务进行分类 2、估算任务时间 3、持续反思评估 对任务进行分类 分类方法&#xff1a;时间管理四象限 A类 B类 C类 D类 估算时间 需要预留休息时间和机动时间 持续反思评估 核对检查任务 自我提问 处理日常干扰的办法 对事情发出提问 对话内容进行…

后端系统开发之——功能完善

原文地址&#xff1a;https://blog.yiming1234.cn/?p830 下面是正文内容&#xff1a; 前言 通过SpringBoot开发用户模块的部分也就差不多要结束了&#xff0c;这一片文章就主要提一些在系统开发中需要注意到的细节部分和功能&#xff0c;也就是剩余的部分。 但是这个专栏只介…

我的创作纪念日 ---- 2024/3/26

前言 2024.3.26是我在CSDN成为创作者的第128天&#xff0c;也是我第一次真正在网上创作的第128天 当我还在日常创作时&#xff0c;突然发现我收到了一封信 我想我可以分享一下这段时间的感想以及收获 机缘 在CSDN的这段时间里&#xff0c;我学习到了很多知识&#xff0c;也…

服务运营 | 印第安纳大学翟成成:改变生活的水井选址

编者按&#xff1a; 作者于2023年4月在“Production and Operations Management”上发表的“Improving drinking water access and equity in rural Sub-Saharan Africa”探讨了欠发达地区水资源供应中的可达性和公平性问题。作者于2020年1月去往非洲埃塞俄比亚提格雷地区进行…

蓝桥杯 2022 省B 砍竹子

思路&#xff1a; 非常明显&#xff0c;这题是个贪心。因为这题是求最小操作次数&#xff0c;而且每次操作都会变小&#xff0c;所以肯定要优先操作大的元素&#xff0c;这样它变小之后才可能和其它元素一起操作以减少操作次数。 所以&#xff1a;建立两个数组&#xff0c;一…

js选择语句

文章目录 1. if 分支语句1.1. 示例代码1.2. 运行结果 2. if 双分支语句3. if 多分支语句4. switch 语句&#xff08;了解&#xff09;4.1. 注意4.2. case 穿透现象4.3. case 穿透产生的原因 5. switch 语句与选择语句区别别5.1. 语法上的区别5.2. 应用场景上的区别 6. 三元表达…

本地GPU调用失败问题解决2修改pytorch版本(失败)

一、基于现有anaconda中的环境复制新环境 1、管理员打开anaconda 进入当前环境&#xff1a; 输入 conda env list conda activate env_pytorch1121 2、复制当前环境为新环境 conda create --name env_pytorch2.2.0cu --clone env_pytorch1121 2&#xff09;删除其中的p…

库存控制秘诀:鞋服品牌如何避免库存积压风险

库存积压对于鞋服品牌而言&#xff0c;是一个普遍而又棘手的问题。过多的库存不仅占用了大量的资金&#xff0c;还可能导致产品过时、贬值&#xff0c;甚至影响品牌的长期发展。因此&#xff0c;如何有效地控制库存&#xff0c;避免积压风险&#xff0c;成为了鞋服品牌必须面对…