Java動態代理的兩種方式

兩種動態代理:

實現原理:
  • JDK動態代理:利用反射機制生成一個實現代理接口的匿名類,在用接口調用具體方法前,調用代理類的invoke來處理。
  • cglib:利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。
cglib和JDK對比
  • 在jdk6之前,cglib比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明爲final的方法進行代理,因爲CGLib原理是動態生成被代理類的子類。
  • 在jdk6、jdk7、jdk8逐步對JDK動態代理優化之後,在調用次數較少的情況下,JDK代理效率高於CGLIB代理效率,只有當進行大量調用的時候,jdk6和jdk7比CGLIB代理效率低一點,但是到jdk8的時候,jdk代理效率高於CGLIB代理。
代碼實例
JDKd動態代理
  • 接口
/**
 * 用戶管理接口(真實主題和代理主題的共同接口,這樣在任何可以使用真實主題的地方都可以使用代理主題代理。)
 * --被代理接口定義
 */
public interface IUserManager {
    void addUser(String id, String password);
}
  • 實現類
/**
 * 用戶管理接口實現(被代理的實現類)
 */
public class UserManagerImpl implements IUserManager {
 
    @Override
    public void addUser(String id, String password) {
        System.out.println("======調用了UserManagerImpl.addUser()方法======");
    }
}
  • JDK動態代理
//JDK動態代理實現InvocationHandler接口
public class JdkProxy implements InvocationHandler {
    private Object target ;//需要代理的目標對象
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK動態代理,監聽開始!");
        Object result = method.invoke(target, args);
        System.out.println("JDK動態代理,監聽結束!");
        return result;
    }
    //定義獲取代理對象方法
    private Object getJDKProxy(Object targetObject){
        //爲目標對象target賦值
        this.target = targetObject;
        //JDK動態代理只能針對實現了接口的類進行代理,newProxyInstance 函數所需參數就可看出
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }
    
    public static void main(String[] args) {
        JdkProxy jdkProxy = new JdkProxy();//實例化JDKProxy對象
        UserManager user = (UserManager) jdkProxy.getJDKProxy(new UserManagerImpl());//獲取代理對象
        user.addUser("admin", "123123");//執行新增方法
    }
    
}
Cglib動態代理
//Cglib動態代理,實現MethodInterceptor接口
public class CglibProxy implements MethodInterceptor {
    private Object target;//需要代理的目標對象
    
    //重寫攔截方法
    @Override
    public Object intercept(Object obj, Method method, Object[] arr, MethodProxy proxy) throws Throwable {
        System.out.println("Cglib動態代理,監聽開始!");
        Object invoke = method.invoke(target, arr);//方法執行,參數:target 目標對象 arr參數數組
        System.out.println("Cglib動態代理,監聽結束!");
        return invoke;
    }
    //定義獲取代理對象方法
    public Object getCglibProxy(Object objectTarget){
        //爲目標對象target賦值
        this.target = objectTarget;
        Enhancer enhancer = new Enhancer();
        //設置父類,因爲Cglib是針對指定的類生成一個子類,所以需要指定父類
        enhancer.setSuperclass(objectTarget.getClass());
        enhancer.setCallback(this);// 設置回調 
        Object result = enhancer.create();//創建並返回代理對象
        return result;
    }
    
    public static void main(String[] args) {
        CglibProxy cglib = new CglibProxy();//實例化CglibProxy對象
        UserManager user =  (UserManager) cglib.getCglibProxy(new UserManagerImpl());//獲取代理對象
        user.delUser("admin");//執行刪除方法
    }
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章