Java动态代理--JDK动态代理

package learn;
import javafx.beans.binding.ObjectExpression; import java.lang.annotation.Target; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * JDK动态代理 */ interface TargetOne { void action(); } interface TargetTwo { void action2(); } class TargetOneImpl implements TargetOne{ @Override public void action() { System.out.println("TargetOneImpl实现TargetOne接口的方法...action"); } } class TargetTwoImpl implements TargetTwo{ @Override public void action2() { System.out.println("TargetTwoImpl实现TargetTwo接口的方法...action2"); } } class TargetAllImpl implements TargetOne,TargetTwo{ @Override public void action() { System.out.println("TargetAllImpl实现TargetOne接口的方法...action"); } @Override public void action2() { System.out.println("TargetAllImpl实现TargetTwo接口的方法...action2"); } /** * 不是实现的接口的方法,动态代理类里面是没有此方法的,无法代理 */ public void action3(){} } /** * 动态代理工厂 */ class DynamicProxy implements InvocationHandler { /** * 接口的一个引用,多态的特性会使得在程序运行的时候,它实际指向的是实现它的子类对象 * object本身只是一个引用,具体指向哪个实现类是我们自己设定的 */ private Object object; DynamicProxy(){ object=null; } DynamicProxy(Object object){ this.object=object; } public Object getObject(){ return this.object; } public void setProxyInterfaceImpl(Object object) { this.object = object; } /** * 获取动态代理类的实例 */ public Object getProxyExample() { /** * 使用Proxy类的静态方法newProxyInstance方法,将代理对象替换为this.object所引用的实现类 public static Object newProxyInstance(ClassLoader loader, //需要被代理的实现类的类加载器 Class<?>[] interfaces, //需要被代理的实现类实现的接口 InvocationHandler h) //实现InvocationHandler代理类的对象 * * 返回值是Proxy类的实例,这个实例实现了传入的实现类所实现的接口 */ return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); } /** * 设置代理实现类 * 获取动态代理类的实例 * * ①将object指向实际实现接口的子类对象 * ②根据被代理类(接口实现类)返回一个代理类对象 * */ public Object getProxyExample(Object object) { this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); } /** * 当通过代理类的对象发起对接口被重写的方法的调用的时候,都会转换为对invoke方法的调用, * 甚至是调用一些实现类的继承的Object的方法也会跳进来,类似于toString * 入参proxy就是Proxy.newProxyInstance获取到的动态代理类 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /** * 静态代理存在的问题:如果不使用反射的情况下,调用具体方法,需要传入具体的接口,既然要传入具体接口,那就不能使用object做为公共引用 * 因为你是在运行前就决定了要代理哪个接口的哪个方法,如果使用Object引用,你是调不了具体接口的方法的; * * 动态代理就可以使用Object作为公共引用,因为Object引用的具体实现类是在运行时决定的,这是一个动态绑定的多态(父类引用到底使用的是 * 哪个实现类,是在运行时决定的)由此还可以在运行时通过反射获取这个实际的被代理的实现类(Proxy类的静态方法newProxyInstance方法 * * Object object=new Object(); System.out.println("调用对象:"+proxy.getClass().getName()); System.out.println(proxy.getClass().getName()+"相对于Object多出的的方法列表:"); Set<String> set=new HashSet<>(); for(Method method1:object.getClass().getMethods()){ set.add(method1.getName()); } for(Method method1:proxy.getClass().getMethods()){ if(!set.contains(method1.getName()))System.out.println(method1.getName()); } 输出: 调用对象:learn.$Proxy0 learn.$Proxy0相对于Object多出的的方法列表: action isProxyClass getInvocationHandler getProxyClass newProxyInstance * * 我们可以轻松得出结论,调用action方法的不是实现类本身,而是通过动态代理生 * 成的learn.$Proxy0类来进行的方法调用,传入不同的实现类,只是给$Proxy0添 * 加了不同接口的方法; * 这也说明了,不仅是接口的方法会传入invoke执行,代理类$Proxy0有的方法都会 * 进入invoke; */ /** * 这里的返回值,就相当于调用真正的实现类的方法的返回值,返回给实际调用者 */ System.out.print("被代理执行:"); Object returnVal = method.invoke(this.object,args); return returnVal; } } public class JavaDynamicProxy { public static void main(String[] args) throws Throwable { /** * 创建代理工厂 */ DynamicProxy dynamicProxy=new DynamicProxy(); /** * 通过反射获取实际被代理的接口实现类的代理类,这个代理类实现了相同的接口,用接口接收这个代理类后,就可以通过这个引用调用接口方法了 */ /** * * TargetOne proxyOne=(TargetOne)dynamicProxy.getProxyExample(); * 注意:返回的是Object类型的引用(被引用的是反射获取的实现了相同接口的Proxy实例),需要强转 * 一下引用类型(因为反射获取的并不是实现类,所以只能转为接口,不能转实现类)不转的话是调不了方法的。 * * dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof TargetOne --->true * dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof Proxy --->true * dynamicProxy.getProxyExample(new TargetOneImpl()) instanceof TargetOneImpl --->false * * 这样写就会报错 * TargetOne proxyOne=(TargetOneImpl) dynamicProxy.getProxyExample(new TargetOneImpl()); * 使用instanceof可以得知返回值是动态生成的Proxy类的实例,并且还实现了TargetOne接口,所以只能强转为接口类型 * (instanceof 测试左边的对象是否是右边的类的实例,返回 boolean 的数据类型) */ /** * 传入具体代理的实现类 * 此时proxyOne实则指向的动态代理类$Proxy0 * 调用动态代理类的方法便会转入invoke */ dynamicProxy.setProxyInterfaceImpl(new TargetOneImpl()); TargetOne proxyOne=(TargetOne)dynamicProxy.getProxyExample(); System.out.println("生成的代理类:"+proxyOne.getClass().getName()); proxyOne.action(); System.out.println("---------------------------------------------"); dynamicProxy.setProxyInterfaceImpl(new TargetTwoImpl()); TargetTwo proxyTwo=(TargetTwo) dynamicProxy.getProxyExample(); System.out.println("生成的代理类:"+proxyTwo.getClass().getName()); proxyTwo.action2(); System.out.println("---------------------------------------------"); DynamicProxy dynamicProxy1=new DynamicProxy(new TargetAllImpl()); System.out.println("生成的代理类:"+dynamicProxy1.getProxyExample().getClass().getName()); ((TargetOne) dynamicProxy1.getProxyExample()).action(); ((TargetTwo) dynamicProxy1.getProxyExample()).action2(); System.out.println("---------------------------------------------"); /** * 代理具体方法的时候可以直接用invoke方法自己通过反射获取并传入具体要代理的Method给invoke方法 */ DynamicProxy dynamicProxy2=new DynamicProxy(new TargetAllImpl()); System.out.println("生成的代理类:"+dynamicProxy2.getProxyExample().getClass().getName()); dynamicProxy2.invoke(null,dynamicProxy2.getObject().getClass().getDeclaredMethod("action"), null); dynamicProxy2.invoke(dynamicProxy2.getProxyExample(),dynamicProxy2.getObject().getClass().getDeclaredMethod("action2"), null); System.out.println("---------------------------------------------"); /** * 检验Class对象的创建规则 */ DynamicProxy dynamicProxy3=new DynamicProxy(new TargetOneImpl()); DynamicProxy dynamicProxy4=new DynamicProxy(new TargetOneImpl()); System.out.println("相同实现类的代理Class对象是否相等:"+dynamicProxy3.getProxyExample().getClass().getName().equals(dynamicProxy4.getProxyExample().getClass().getName())); System.out.println("相同实现类的代理实例是否相等:"+dynamicProxy3.equals(dynamicProxy4)); System.out.println("---------------------------------------------"); /** * 输出: * * 生成的代理类:learn.$Proxy0 * 被代理执行:TargetOneImpl实现TargetOne接口的方法...action * --------------------------------------------- * 生成的代理类:learn.$Proxy1 * 被代理执行:TargetTwoImpl实现TargetTwo接口的方法...action2 * --------------------------------------------- * 生成的代理类:learn.$Proxy2 * 被代理执行:TargetAllImpl实现TargetOne接口的方法...action * 被代理执行:TargetAllImpl实现TargetTwo接口的方法...action2 * --------------------------------------------- * 生成的代理类:learn.$Proxy2 * 被代理执行:TargetAllImpl实现TargetOne接口的方法...action * 被代理执行:TargetAllImpl实现TargetTwo接口的方法...action2 * --------------------------------------------- * 相同实现类的代理Class对象是否相等:true * 相同实现类的代理实例是否相等:false * --------------------------------------------- * * Process finished with exit code 0 * * 从输出还能看出,代理工厂生成代理类Class对象的类别是根据实现类生成,不同的实现类会生成不同的代理Class对象 * 但是每个工厂的实例是不一样的System.out.println(dynamicProxy2.equals(dynamicProxy1)); */ } }

 

posted @ 2021-09-28 15:34  忙碌了一整天的L师傅  阅读(92)  评论(0编辑  收藏  举报