Loading... 当我们需要通过注解的方式来判断一个类以及这个类的方法需要不要使用动态代理,就会发现动态代理的内部是无法获取到方法的注解信息的,通过一个例子来看,还是使用上一篇文章中所创建的对象信息。 <div class="preview"> <div class="post-inser post box-shadow-wrap-normal"> <a href="https://www.kezez.com/archives/195.html" target="_blank" class="post_inser_a no-external-link no-underline-link"> <div class="inner-image bg" style="background-image: url(https://www.kezez.com/usr/themes/handsome/assets/img/sj/5.jpg);background-size: cover;"></div> <div class="inner-content" > <p class="inser-title">Java 静态代理和动态代理模式</p> <div class="inster-summary text-muted"> Java的动态代理是指在程序运行的时候,通过代理对象去调用目标对象的方法,同时在调用目标方法的前后可以执行一些功能... </div> </div> </a> <!-- .inner-content #####--> </div> <!-- .post-inser ####--> </div> ## 创建注解 作用于类上的注解`AnnotationInClass` ```java package com.kezez.java; import java.lang.annotation.*; /** * @author : kaygb * @date : 2022/7/23 19:39 * @desc : * @website : https://www.170601.xyz/ * @blog : https://www.kezez.com/ * @github : https://github.com/kaygb */ @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface AnnotationInClass { } ``` 作用于方法上的注解`AnnotationInMethod` ```java package com.kezez.java; import java.lang.annotation.*; /** * @author : kaygb * @date : 2022/7/23 19:40 * @desc : * @website : https://www.170601.xyz/ * @blog : https://www.kezez.com/ * @github : https://github.com/kaygb */ @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AnnotationInMethod { } ``` ## 创建实体类 创建实体类`BirdTwo`实现`Bird`接口(Bird接口为上篇文章创建) ```java package com.kezez.java; /** * @author : kaygb * @date : 2022/7/23 19:44 * @desc : * @website : https://www.170601.xyz/ * @blog : https://www.kezez.com/ * @github : https://github.com/kaygb */ @AnnotationInClass public class BirdTwo implements Bird { public BirdTwo() { } @AnnotationInMethod @Override public void fly() { System.out.println("fly"); } } ``` 创建动态代理 ```java package com.kezez.java; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @author : kaygb * @date : 2022/7/23 19:41 * @desc : * @website : https://www.170601.xyz/ * @blog : https://www.kezez.com/ * @github : https://github.com/kaygb */ public class DynamicProxy implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (target.getClass().isAnnotationPresent(AnnotationInClass.class)) { System.out.println("类上有注解"); } if (method.isAnnotationPresent(AnnotationInMethod.class)) { System.out.println("方法上有注解"); } System.out.println("动态代理:打开鸟笼的门"); Object res = method.invoke(target, args); return res; } } ``` 通过`isAnnotationPresent`方法传入注解的类可以判断是方法或者类上是否使用了此注解,执行后我们可以发现,动态代理方法只输出了类上的注解,而并没有获取到方法上的注解。 ```txt 类上有注解 动态代理:打开鸟笼的门 fly ``` ## 问题导致的原因 为啥获取不到方法中的注解呢?其实是因为`Proxy.newProxyInstance`传入的是被代理对象的接口,而不是具体的实现类,所以只能获取到接口方法上的注解而获取不到实现类上的注解。 ```java Proxy.newProxyInstance(birdTwo.getClass().getClassLoader(), birdTwo.getClass().getInterfaces(), dynamicProxy); ``` ## 解决动态代理无法获取实现类方法上的注解 那么如何解决?其实也很简单,我们在创建`DynamicProxy`时,为此动态代理对象创建了一个属性传入了具体的目标对象`target`,我们可以通过动态代理中的`method.getName()`获取到方法的名称,然后使用`target.getClass().getMethod(method.getName())`获取到目标对象实现类的方法,获取到实现类的方法,具体如下: ```java target.getClass().getMethod(method.getName()).isAnnotationPresent(AnnotationInMethod.class) ``` 完整的代码如下所示: ```java package com.kezez.java; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * @author : kaygb * @date : 2022/7/23 19:41 * @desc : * @website : https://www.170601.xyz/ * @blog : https://www.kezez.com/ * @github : https://github.com/kaygb */ public class DynamicProxy implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (target.getClass().isAnnotationPresent(AnnotationInClass.class)) { System.out.println("类上有注解"); } if (method.isAnnotationPresent(AnnotationInMethod.class)) { System.out.println("方法上有注解"); } if (target.getClass().getMethod(method.getName()).isAnnotationPresent(AnnotationInMethod.class)) { System.out.println("实现类的方法上有注解"); } System.out.println("动态代理:打开鸟笼的门"); Object res = method.invoke(target, args); return res; } } ``` 执行main方法 ```java package com.kezez.java; import java.lang.reflect.Proxy; public class Main { public static void main(String[] args) { // Bird birdOne = new BirdOne(); // Birdcage birdcage = new Birdcage(birdOne); // birdcage.fly(); Bird birdTwo = new BirdTwo(); DynamicProxy dynamicProxy = new DynamicProxy(); dynamicProxy.setTarget(birdTwo); Object obj = Proxy.newProxyInstance(birdTwo.getClass().getClassLoader(), birdTwo.getClass().getInterfaces(), dynamicProxy); ((Bird) obj).fly(); } } ``` 输出的结果如下: ```txt 类上有注解 实现类的方法上有注解 动态代理:打开鸟笼的门 fly ``` © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏
4 条评论
看不懂+1 ̄﹃ ̄
哈哈OωO
表示看不懂
哈哈,慢慢学就会了