Spring AOP 进阶:揭秘 @annotation 参数绑定的底层逻辑
Spring AOP 进阶揭秘 annotation 参数绑定的底层逻辑在使用 Spring AOP 开发自定义注解如RateLimit时我们经常会看到这样一种“神奇”的写法Around(annotation(rateLimit))publicObjectcheckLimit(ProceedingJoinPointjoinPoint,RateLimitrateLimit){// ...}很多开发者会有疑问为什么必须在方法参数里声明RateLimit rateLimit才能使用rateLimit对象如果不写参数还能拿到注解信息吗这涉及到了 Spring AOP 中极具“黑魔法”色彩的设计——参数绑定。本文将深入浅出地拆解这一机制。一、 两种拦截模式“看一眼”还是“拿过来”在切面里拦截注解其实有两种完全不同的写法代表了两种不同的需求层次。1. 需求一仅作为“标记”如果你的注解里面没有任何属性例如LogExecutionTime切面只需要知道“这个方法有没有贴标签”而不需要读取标签上的内容。这时候你可以把注解的全限定名写死在括号里方法参数里什么都不用加// 保安只认通行证的款式不看上面的字Around(annotation(com.yourproject.annotation.LogExecutionTime))publicObjectlogTime(ProceedingJoinPointjoinPoint){// 直接执行逻辑因为不需要读取注解属性returnjoinPoint.proceed();}2. 需求二读取“配置信息”但在RateLimit的场景中你需要读取注解里配置的time 60和maxCount 5。这意味着你必须把那个活生生的注解对象拿到手。如果你不在方法参数里声明Spring 就会认为“你只是让我拦截它没说要把它交给你啊”于是你在方法内部就拿不到注解对象。二、 参数绑定Spring 的“三方协议”当你写出下面这段代码时其实是在和 Spring 签订一份**“变量绑定协议”**// 协议第一步告诉 Spring拦截到的那个注解请将其命名为 rateLimitAround(annotation(rateLimit))// 协议第二步Spring 拿着这个名字来参数列表里找。// 发现确实有个变量叫 rateLimit名字对上了而且类型是 RateLimit类型也对上了。publicObjectcheckLimit(ProceedingJoinPointjoinPoint,RateLimitrateLimit){// 交易成功Spring 乖乖把那个注解对象塞进这个参数里交给你。longtimerateLimit.time();// ...}这就是为什么必须在方法参数里写的原因你需要 Spring 把截获的“战利品注解对象”通过参数传递给你。三、 如果不写参数能拿到注解吗硬核解法如果你非要头铁偏不在参数里写RateLimit rateLimit你还能拿到注解里的属性吗答案是能但极其痛苦。你需要手写繁琐的 Java 反射代码。这也是为什么 Spring 要提供参数绑定功能的原因——为了避免让开发者写下面这种“反人类”的代码// 1. 括号里写死全路径Around(annotation(com.yourproject.annotation.RateLimit))publicObjectcheckLimit(ProceedingJoinPointjoinPoint)throwsThrowable{// // 极其痛苦的反射获取注解三步曲// // 1. 先拿到目标方法的签名信息MethodSignaturesignature(MethodSignature)joinPoint.getSignature();// 2. 通过签名拿到真实的 Method 对象Methodmethodsignature.getMethod();// 3. 用反射从 Method 对象上强行抠下 RateLimit 注解对象RateLimitrateLimitmethod.getAnnotation(RateLimit.class);// 拿到之后才能正常读取属性longtimerateLimit.time();intmaxCountrateLimit.maxCount();returnjoinPoint.proceed();}你看为了拿到那个注解对象我们写了三行晦涩的反射代码。Spring 的伟大之处就在于此它为了不让你写上面那段代码特意发明了Around(annotation(xxx))配合方法参数的语法糖。你只需要在参数里声明一下Spring 框架在底层就会自动帮你把那段繁琐的反射代码执行完然后把现成的结果递到你手上。总结不带参数的写法适合纯标记型注解如LogExecutionTime、Transactional。切面只关心“有没有贴注解”不关心注解里的内容。变量绑定的写法适合配置型注解如RateLimit(time60)。切面不仅要拦截还要读取注解内部配置的参数值。理解了这一点你就彻底搞懂了 Spring AOP 切面编程中最核心的数据传递机制。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2433940.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!