动态代理的个人理解笔记
JDK动态代理
jdk动态代理是代理模式的一种实现方式,只能代理接口interface
原因:代理对象要对被代理对象属性功能进行增强。
二者之间必须要有共同的方法(方法名一致)
代理对象通过重写 @override 被代理对象的方法来对被代理对象进行增强
总结:动态代理对象,代理的就是接口的实现类,重写实现类的方法(也是接口的方法)来对实现类进行增强。
1.新建一个接口Subject
2.为这个接口创建一个实现类 SubjectImpl
3.创建java.lang.reflect.InvocationHandler接口的实现类,对接口SubjectImpl方法进行增强
4.创建动态代理对象,并对结果验证测试
演示:
1.创建一个接口
/** * 创建一个接口 * 包含共同的方法doSomething */ public interface Subject { void doSomething(); }
2.创建这个接口的实现类
1 package com.Proxy; 2 3 /** 4 * @Version V1.0 5 * @Author: leo 6 * @Date: 2019-12-15 15:42 7 * @Description:创建接口的真实实现类 8 */ 9 public class SubjectImpl implements Subject { 10 11 @Override 12 public void doSomething() { 13 System.out.println("我是接口的实现类SubjectImpl,重写实现了接口的doSomething()方法"); 14 15 } 16 }
1 package com.Proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 /** 7 * @Version V1.0 8 * @Author: leo 9 * @Date: 2019-12-15 17:53 10 * @Description:InvocationHandler接口实现类, 11 * 通过重写invoHandler接口中的invoke方法对代理对象(接口Subject的实现类SubjectImpl的对象) 12 * 实现的接口(Subject接口)中的方法(doSomething())进行增强; 13 */ 14 public class InvocationHandlerImpl implements InvocationHandler { 15 16 //method方法执行时候需要 SubjectImpl的实现类,这里对象给一个最大的类对象 17 private Object object; 18 public InvocationHandlerImpl(Object object) { 19 this.object = object; 20 } 21 22 /** 23 * @param proxy Subject接口的实现类SubjectImpl的动态代理对象。 24 * @param method 需要增强的方法对象可以通过反射获得。 25 * method = SubjectImpl.class.getDeclaredMethod(); 26 * @param args 上述增强的方法的参数们(方法可能有多个参数,所以是一个参数数组) 27 * @return invoke 28 * @throws Throwable 29 */ 30 @Override 31 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 32 33 method.setAccessible(true); 34 System.out.println("SubjectImpl的doSomething()方法增强前"); 35 36 //这里通过反射,object为执行方法的对象,这里是被代理对象SubjectImpl的实现类对象,args是参数 37 Object invoke = method.invoke(object, args); 38 System.out.println("SubjectImpl的doSomething()方法增强后"); 39 return invoke; 40 } 41 }
1 package com.Proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 /** 8 * @Version V1.0 9 * @Author: leo 10 * @Date: 2019-12-15 17:32 11 * @Description:创建接口Subject实现类SUbjectImpl的动态代理对象。 12 */ 13 public class SubjectProxy { 14 15 public static void main(String[] args) { 16 17 InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl( new SubjectImpl()); 18 19 /** 20 * 创建动态代理对象 21 * 创建代理对象方法newProxyInstance(loader,interfaces,h) 22 * 参数1:类加载器,作用:将代理类加载到JVM方法区中去 23 * 参数2:表示代理类和被代理类的共同父接口们,属于Class类型。 24 * 问题1:为什么这里需要父接口? 25 * 因为被代理类和代理类要有共同的方法,只有这里将父接口传递到底层, 26 * 那么生成的代理类对象才可以调用共同方法 27 * 问题2:这里怎么提供? 28 * Class<?>[] interfaces = {Subject.class}; 29 * 根据反射机制,使用Class类中的方法可以获取共同父接口们。 30 * Class<?>[] getInterfaces() 确定此对象所表示的类或接口实现的接口。 31 * object.getClass().getInterfaces(); 32 * 33 * 参数3:h:invocationHandle实现类对象,对接口和实现类的共有方法进行增强。 34 */ 35 Subject proxyInstance = (Subject) Proxy.newProxyInstance(SubjectProxy.class.getClassLoader(), new Class[]{Subject.class}, invocationHandler 36 ); 37 System.out.println("创建了动态代理对象,下面是动态代理对方法增强的效果"); 38 proxyInstance.doSomething(); 39 } 40 }
执行结果如下:
创建了动态代理对象,下面是动态代理对方法增强的效果
SubjectImpl的doSomething()方法增强前
我是接口的实现类SubjectImpl,重写实现了接口的doSomething()方法
SubjectImpl的doSomething()方法增强后