当前位置: 首页 > news >正文

springboot~获取原注解的方法findMergedAnnotation使用场景

这是一个很好的问题,涉及到Spring注解的元注解处理和属性别名机制。让我详细解释一下Spring JMS是如何获取到你自定义注解中的destination值的。

核心机制:Spring的注解属性别名(Attribute Aliasing)

当你在自定义注解中使用@AliasFor@JmsListener的destination属性赋值时,Spring通过以下步骤处理:

1. 注解处理流程

// 你的自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@JmsListener
public @interface MyCustomJmsListener {@AliasFor(annotation = JmsListener.class, attribute = "destination")String value() default "";// 其他属性...
}

2. Spring JMS的内部处理机制

JmsListenerAnnotationBeanPostProcessor是处理@JmsListener的核心类:

// 简化的处理逻辑
public class JmsListenerAnnotationBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {// 扫描bean的方法,查找JmsListener注解for (Method method : bean.getClass().getMethods()) {// 这里会使用Spring的AnnotationUtils找到注解JmsListener jmsListener = AnnotatedElementUtils.findMergedAnnotation(method, JmsListener.class);if (jmsListener != null) {processJmsListener(jmsListener, method, bean);}}return bean;}private void processJmsListener(JmsListener jmsListener, Method method, Object bean) {// 获取destination值String destination = jmsListener.destination();// 创建监听器容器...}
}

3. 关键方法:AnnotatedElementUtils.findMergedAnnotation()

这是Spring处理注解属性的核心方法:

// Spring内部的处理逻辑
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {// 1. 查找直接或元注解Annotation[] annotations = element.getAnnotations();for (Annotation ann : annotations) {// 2. 如果是目标注解直接返回if (annotationType.isInstance(ann)) {return (A) ann;}// 3. 递归处理元注解Annotation[] metaAnnotations = ann.annotationType().getAnnotations();for (Annotation metaAnn : metaAnnotations) {if (annotationType.isInstance(metaAnn)) {// 4. 处理属性别名映射return synthesizeAnnotation(ann, metaAnn, element);}}}return null;
}

4. 属性别名解析过程

private static <A extends Annotation> A synthesizeAnnotation(Annotation sourceAnnotation, Annotation metaAnnotation, AnnotatedElement element) {Map<String, Object> attributeMap = new HashMap<>();// 获取元注解的属性Method[] metaMethods = metaAnnotation.annotationType().getDeclaredMethods();for (Method metaMethod : metaMethods) {String attributeName = metaMethod.getName();// 检查源注解是否有对应的别名属性Method sourceMethod = findAliasMethod(sourceAnnotation, attributeName);if (sourceMethod != null) {// 使用源注解的值覆盖元注解的值Object value = invokeMethod(sourceMethod, sourceAnnotation);attributeMap.put(attributeName, value);} else {// 使用元注解的默认值Object value = invokeMethod(metaMethod, metaAnnotation);attributeMap.put(attributeName, value);}}// 创建合成注解return AnnotationUtils.synthesizeAnnotation(attributeMap, metaAnnotation.annotationType(), element);
}

5. 实际示例

假设你的使用方式如下:

@Component
public class MyMessageListener {@MyCustomJmsListener("my-queue")public void handleMessage(String message) {// 处理消息}
}

Spring JMS的处理过程:

  1. 发现注解:扫描到@MyCustomJmsListener注解
  2. 识别元注解:发现@MyCustomJmsListener@JmsListener元注解标记
  3. 属性合并:通过@AliasForvalue="my-queue"映射到destination属性
  4. 创建监听器:使用合成后的@JmsListener(destination = "my-queue")创建JMS监听容器

6. 验证方法

你可以通过以下方式验证这个机制:

@SpringBootTest
class JmsListenerTest {@Autowiredprivate JmsListenerEndpointRegistry endpointRegistry;@Testvoid testCustomAnnotation() {// 检查监听器容器是否创建成功Collection<MessageListenerContainer> containers = endpointRegistry.getListenerContainers();for (MessageListenerContainer container : containers) {if (container instanceof JmsListenerEndpointRegistry) {// 验证destination是否正确设置String destination = ((AbstractJmsListenerContainer) container).getDestination();System.out.println("监听的destination: " + destination);}}}
}

总结

Spring通过AnnotatedElementUtils和注解属性别名机制,能够正确识别你自定义注解中通过@AliasFor映射的属性值。这种设计使得注解组合和自定义变得非常灵活,是Spring框架强大的元编程能力的体现。

http://www.hskmm.com/?act=detail&tid=14843

相关文章:

  • Catalan数(卡特兰数)
  • IvorySQL文档共建计划第一期!提 PR,提 Issue,赢取 Beats 耳机、机械键盘、书籍等多重好礼!
  • ubuntu22.04 安装xrdp
  • 题解:P14058 【MX-X21-T3】[IAMOI R5] 两个人的演唱会
  • 深入解析Wallarm安全边缘:API边缘的即时防护技术
  • 字符串
  • 总线的概念以及分类
  • A Great Beginning
  • 邮件系统的未来趋势:技术革新与智能化的未来
  • docker volume使用
  • 52805 JLINK 端口保护机制硬件保护具体流程分析;
  • 构建你的 MCP 能力层:.NET 9 + SK 的系统方案
  • pl/sql使用
  • PLC中的运动控制 - (二)基本控制指令MC_Power,MC_Stop,MC_Halt
  • FOC之电机模型
  • 使用shell脚本一键部署docker及docker-compose环境
  • paddleOCR 图片识别
  • 使用命令行powershell修改系统变量
  • 数据全生命周期安全建设方案推荐:双轮驱动架构的实践与创新
  • 赋能智慧水利:国标GB28181平台EasyGBS在农业水文监控中的落地实践
  • VS依赖项显示黄色感叹号、红色叉叉,NU1101找不到包异常情况处理方案
  • 噬菌体展示技术原理深度解析:从基因型-表型偶联到亲和筛选的核心逻辑
  • AT_arc197_e [ARC197E] Four Square Tiles
  • 不限速网盘盘点,五款免费网盘综合对比
  • 日记2
  • RTK精度和时间 - MKT
  • LeetCode-100.相同的树
  • ubuntu安装minio并切换数据存储目录
  • 学习笔记508— 威联通安装使用Zerotier One
  • Java 语法糖大揭秘:让代码更甜更高效的幕后功臣 - 教程