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

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

问题描述


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


问题示例代码


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


@Component
public class TestBean {
    @Anno
    public void test() {
        System.out.println("test .....");
    }
}


  1. 代理逻辑逻辑处理, 主要就是做一个 @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();
    }
}


  1. 调用点, 通过 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 提供了非常强大的一站式开发功能,而且还提供了比较优秀的工具方法比如: BeanUtilsReflectionUtilsAnnotationUtils 等,这些都是我们值得掌握的基础工具类。


参考资料



相关文章
|
15天前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
102 26
|
18天前
|
缓存 Java 数据库
SpringBoot缓存注解使用
Spring Boot 提供了一套方便的缓存注解,用于简化缓存管理。通过 `@Cacheable`、`@CachePut`、`@CacheEvict` 和 `@Caching` 等注解,开发者可以轻松地实现方法级别的缓存操作,从而提升应用的性能和响应速度。合理使用这些注解可以大大减少数据库的访问频率,优化系统性能。
166 89
|
2月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
181 73
|
5天前
|
监控 Java Spring
SpringBoot:SpringBoot通过注解监测Controller接口
本文详细介绍了如何通过Spring Boot注解监测Controller接口,包括自定义注解、AOP切面的创建和使用以及具体的示例代码。通过这种方式,可以方便地在Controller方法执行前后添加日志记录、性能监控和异常处理逻辑,而无需修改方法本身的代码。这种方法不仅提高了代码的可维护性,还增强了系统的监控能力。希望本文能帮助您更好地理解和应用Spring Boot中的注解监测技术。
33 16
|
2月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
60 21
|
2月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
28天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
211 17
Spring Boot 两种部署到服务器的方式
|
28天前
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
61 17
springboot自动配置原理
|
1月前
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
82 11
|
1月前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
354 12