Spring 代理 Bean 获取不到原始 Bean 对象注解解决方法

作者:心城以北 时间:2022-10-31 17:06:08 

一、问题描述

在接受 mq 消息的时候,需要做一个重试次数限制,如果超过 maxNum 就发邮件告警,不再重试。 所以我需要对 consumer 对象进行代理,然后如果超过异常次数,我直接返回成功,并且发送成功消息,但是我获取 consumer handler 方法的方式是通过 method.getAnnotation(XXClient.class) 方式,那么就会返回 null。

1.问题示例代码

  • 目标类, 我这里就之定义一个 test 方法,里面做一些个简单的打印。

@Component
public class TestBean {

@Anno
   public void test() {
       System.out.println("test .....");
   }
}
  • 代理逻辑逻辑处理, 主要就是做一个 @Around 的方法覆盖,保证在调用目标方法之前,先输出我插入的逻辑。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Anno {

String key() default "100%";
}

@Aspect
@Component
public class AnnoAspect {

@Around("@annotation(anno)")
   public Object anno(ProceedingJoinPoint point, Anno anno) throws Throwable {
       System.out.println("anno invoke!!!!!!");
       return point.proceed();
   }

}
  • 调用点, 通过 AnnotationConfigApplicationContext 获取 bean. 然后通过 getMethods() 获取所有的方法,最后查找 Anno 注解的 Method 对象。

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanStart.class);
   TestBean bean = applicationContext.getBean(TestBean.class);

Class<? extends TestBean> classz = bean.getClass();
   Method[] methods = classz.getMethods();

for (Method m : methods) {
       Anno annotation = m.getAnnotation(Anno.class);

if (annotation != null) {
           System.out.println(" ============= invoke test ===========");
           m.invoke(bean, new Object());
       }
   }

由于 m.getAnnotaion(Anno.class) 无法获取到注解信息,所以执行 test 方法失败, 到此问题还原完毕,我们再来看看如何解决。

二、解决方案

通过 Anno ao = AnnotationUtils.findAnnotation(method, Anno.class); 方法获取即可。

有的代码是这样写的 :

String name = classz.getName();
boolean isSpringProxy = name.indexOf("SpringCGLIB$$") >= 0;
Method[] methods;
if (isSpringProxy) {
   methods = ReflectionUtils.getAllDeclaredMethods(AopUtils.getTargetClass(bean));
} else {
   methods = classz.getMethods();
}

// 省略部分代码
if (isSpringProxy) {
   annotation = AnnotationUtils.findAnnotation(method, MqClient.class);
} else {
   annotation = method.getAnnotation(Anno.class);
}

这里他会做一个判断,如果是代理对象就调用 ReflectionUtils.getAllDeclaredMethods 获取所有的方法, 然后再去拿注解的时候二次判断一下,如果存在代理,那么就通过 AnnotationUtils.findAnnotation 感觉是相当的严谨。

总结:

Spring 提供了非常强大的一站式开发功能,而且还提供了比较优秀的工具方法比如: BeanUtils 、ReflectionUtils 、AnnotationUtils 等,这些都是我们值得掌握的基础工具类。

来源:https://juejin.cn/post/7081635762562662413

标签:Spring,代理,Bean,获取,原始,对象,注解
0
投稿

猜你喜欢

  • Java中二叉树数据结构的实现示例

    2023-08-07 03:10:58
  • springboot集成elasticsearch7的图文方法

    2022-05-15 19:46:11
  • JVM教程之内存管理和垃圾回收(三)

    2023-11-10 15:49:54
  • java 实现发短信功能---腾讯云短信

    2023-11-29 11:03:49
  • SpringBoot实现分页功能

    2021-11-07 12:33:16
  • opencv 做人脸识别 opencv 人脸匹配分析

    2023-07-09 06:34:44
  • Spring Security 实现短信验证码登录功能

    2022-11-02 19:39:30
  • springboot中项目启动时实现初始化方法加载参数

    2023-08-31 06:00:40
  • Spring拦截器HandlerInterceptor接口代码解析

    2022-09-05 10:51:04
  • Android Flutter中Offstage组件的使用教程详解

    2023-08-20 01:01:44
  • 使用JAVA实现http通信详解

    2023-11-12 12:21:12
  • Java Comparable及Comparator接口区别详解

    2023-07-03 08:19:50
  • Java中弱引用和软引用的区别以及虚引用和强引用介绍

    2023-01-23 18:55:33
  • @ConfigurationProperties加载外部配置方式

    2023-11-09 01:14:32
  • IDEA中配置文件模板的添加方法

    2023-10-28 17:52:31
  • Java排序之冒泡排序的实现与优化

    2023-11-10 21:35:56
  • Mybatis RowBounds 限制查询条数的实现代码

    2022-11-18 17:26:03
  • Mybatis常用分页插件实现快速分页处理技巧

    2022-12-25 00:03:45
  • Java中常见的编码集问题总结

    2023-11-29 01:40:04
  • Java封装、继承、多态三大特征的理解

    2023-07-16 14:26:46
  • asp之家 软件编程 m.aspxhome.com