4.JDK動態(tài)代理和CGlib代理

JDK動態(tài)代理:

利用攔截器(攔截器必須實現InvocationHanlder)加上反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。

CGLiB動態(tài)代理:
利用ASM開源包,對代理對象類的class文件加載進來,通過修改其字節(jié)碼生成子類來處理。

何時使用JDK還是CGLiB?

1、如果目標對象實現了接口,默認情況下會采用JDK的動態(tài)代理實現AOP。
2、如果目標對象實現了接口,可以強制使用CGLIB實現AOP。
3、如果目標對象沒有實現了接口,必須采用CGLIB庫,Spring會自動在JDK動態(tài)代理和CGLIB之間轉換。

如何強制使用CGLIB實現AOP?
1、添加CGLIB庫(aspectjrt-xxx.jar、aspectjweaver-xxx.jar、cglib-nodep-xxx.jar)
2、在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK動態(tài)代理和CGLIB字節(jié)碼生成的區(qū)別?
1、JDK動態(tài)代理只能對實現了接口的類生成代理,而不能針對類。
2、CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,并覆蓋其中方法實現增強,但是因為采用的是繼承,所以該類或方法最好不要聲明成final,對于final類或方法,是無法繼承的。

CGlib比JDK快?

1、使用CGLib實現動態(tài)代理,CGLib底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術生成代理類,
在jdk6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明為final的方法進行代理,
因為CGLib原理是動態(tài)生成被代理類的子類。
2、在jdk6、jdk7、jdk8逐步對JDK動態(tài)代理優(yōu)化之后,在調用次數較少的情況下,JDK代理效率高于CGLIB代理效率,只有當進行大量調用的時候,jdk6和jdk7比CGLIB代理效率低一點,但是到jdk8的時候,jdk代理效率高于CGLIB代理,總之,每一次jdk版本升級,jdk代理效率都得到提升,而CGLIB代理消息確有點跟不上步伐。

Spring如何選擇用JDK還是CGLiB?

1、當Bean實現接口時,Spring就會用JDK的動態(tài)代理。
2、當Bean沒有實現接口時,Spring使用CGlib是實現。
3、可以強制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)。

JDK動態(tài)代理實現

public interface UserManager {
    //新增用戶抽象方法
    void addUser(String userName,String password);
    //刪除用戶抽象方法
    void delUser(String userName);
}
public class UserManagerImpl implements UserManager {
    //重寫新增用戶方法
    @Override
    public void addUser(String userName, String password) {
        System.out.println("調用了新增的方法!");
        System.out.println("傳入參數為 userName: "+userName+" password: "+password);
    }
    //重寫刪除用戶方法
    @Override
    public void delUser(String userName) {
        System.out.println("調用了刪除的方法!");
        System.out.println("傳入參數為 userName: "+userName);
    }
}
public class JdkProxy implements InvocationHandler {

    private Object target;//需要代理的目標對象

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("JDK動態(tài)代理,監(jiān)聽開始!");
        Object result = method.invoke(target, args);
        System.out.println("JDK動態(tài)代理,監(jiān)聽結束!");
        return result;
    }

    //定義獲取代理對象方法
    private Object getJDKProxy(Object targetObject) {
        //為目標對象target賦值
        this.target = targetObject;
        //JDK動態(tài)代理只能針對實現了接口的類進行代理,newProxyInstance 函數所需參數就可看出
        System.out.println(this.getClass());
        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");//執(zhí)行新增方法
    }
}

CGlib實現

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動態(tài)代理,監(jiān)聽開始!");
        Object invoke = method.invoke(target, arr);//方法執(zhí)行,參數:target 目標對象 arr參數數組
        System.out.println("Cglib動態(tài)代理,監(jiān)聽結束!");
        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();//創(chuàng)建并返回代理對象
        return result;
    }

    public static void main(String[] args) {
        CglibProxy cglib = new CglibProxy();//實例化CglibProxy對象
        UserManager user =  (UserManager) cglib.getCglibProxy(new UserManagerImpl());//獲取代理對象
        user.delUser("admin");//執(zhí)行刪除方法
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容