1、首先我們了解一下JDK動態代理的使用方法:
public static void main(String[] args) { /** * 創建一個Bean對象,該對象實現BeanInterFace接口 */ BeanInterFace bean = new Bean(); /** * 創建一個MyProxy對象,該對象實現InvocationHandler接口,將bean注入到MyProxy中 */ InvocationHandler invocationHandler = new MyProxy(bean); /** * 調用JDK的Proxy類,使用newProxyInstance方法,直接生成Bean對象的代理對象 * 注意:Classloader必須采用實際代理對象的ClassLoader,否則會出現反復調用的問題 */ BeanInterFace beanProxy = (BeanInterFace) Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(),invocationHandler); /** * 使用代理對象 */ System.out.println(beanProxy.getClass().getName()); beanProxy.say(); }
2、我們看一下JDK源碼,是如何實現動態代理的
Proxy.newProxyInstance最終會調用Proxy.ProxyClassFactory.apply()方法生成代理Class
//創建proxyname,通過package+ClassName+編號
String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * 這裡生成了代理的Class,並編譯返回二進制byte[]數組 */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try {
//這裡加載了ProxyClass,這裡的加載用的是系統appClassLoader,至今我還沒明白怎麼才能使用,JDK使用的native方法 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); }
3、具體proxyClass是如何生成的
大致就是:
proxyClass有一個構造函數,該構造函數的參數為InvocationHandler接口,proxyClass實例化以後將InvocationHandler的引用儲存在自己的屬性中,然後proxyClass每個方法的觸發都會觸發InvocationHandler的invoke方法,通過反射調用真實對象的的方法。