1. 程式人生 > >理解什麼是動態代理及程式碼的實現

理解什麼是動態代理及程式碼的實現

jdk動態代理是由java內部的反射機制來實現的,cglib動態代理底層則是藉助asm來實現的。總的來說,反射機制在生成類的過程中比較高效,而asm在生成類之後的相關執行過程中比較高效(可以通過將asm生成的類進行快取,這樣解決asm生成類過程低效問題)。還有一點必須注意:jdk動態代理的應用前提,必須是目標類基於統一的介面。如果沒有上述前提,jdk動態代理不能應用。
1、定義介面和實現
(1)package com.baidu.dyProxy;
public interface UserServiceI {
void add();
void delete();
}
(2)package com.baidu.dyProxy;
public class UserServiceImpl implements UserServiceI{
@Override
public void add() {
System.out.println("add方法 ");
}
@Override
public void delete() {
System.out.println(“delete方法”)
}
}
2.jdk動態代理實現
package com.baidu.dyProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理類
public class MyProxy implements InvocationHandler {
private Object target;
//要代理很多物件,所以用Object
public Object getProxy(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//程式程式碼呼叫處
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//目標方法的執行
Object returnValue = method.invoke(target, args);
return returnValue;
}
}
3.測試:
package com.baidu.dyProxy;
public class Test {
public static void main(String[] args) {
MyProxy proxy = new MyProxy();
UserServiceImpl serviceImpl = new UserServiceImpl();
//獲取代理物件
UserServiceI userServiceI = (UserServiceI) proxy.getProxy(serviceImpl);
userServiceI.add();
}
}

說明一下:Proxy.newProxyInstance()方法有三個引數:

  1. 類載入器(Class Loader)

  2. 需要實現的介面陣列

  3. InvocationHandler介面。所有動態代理類的方法呼叫,都會交由InvocationHandler介面實現類裡的invoke()方法去處理。這是動態代理的關鍵所在。

  4. invoke()方法同樣有三個引數:

  5. 動態代理類的引用,通常情況下不需要它。但可以使用getClass()方法,得到proxy的Class類從而取得例項的類資訊,如方法列表,annotation等。

  6. 方法物件的引用,代表被動態代理類呼叫的方法。從中可得到方法名,引數型別,返回型別等等

  7. args物件陣列,代表被呼叫方法的引數。注意基本型別(int,long)會被裝箱成物件型別(Interger, Long)