最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析動(dòng)態(tài)代理jdk的Proxy與spring的CGlib(包括區(qū)別介紹)

 更新時(shí)間:2022年01月22日 11:58:06   作者:三只蛋黃派  
Spring是Java程序員基本不可能繞開(kāi)的一個(gè)框架,它的核心思想是IoC(控制反轉(zhuǎn))和AOP(面向切面編程)。本文重點(diǎn)給大家介紹動(dòng)態(tài)代理jdk的Proxy與spring的CGlib,感興趣的朋友跟隨小編一起看看吧

1. 為什么要使用動(dòng)態(tài)代理?

動(dòng)態(tài)代理:在不改變?cè)写a的情況下上進(jìn)行對(duì)象功能增強(qiáng) 使用代理對(duì)象代替原來(lái)的對(duì)象完成功能 進(jìn)而達(dá)到拓展功能的目的

2.JDK Proxy 動(dòng)態(tài)代理面向接口的動(dòng)態(tài)代理

特點(diǎn):

  • 一定要有接口和實(shí)現(xiàn)類(lèi)的存在 代理對(duì)象增強(qiáng)的是實(shí)現(xiàn)類(lèi) 在實(shí)現(xiàn)接口的方法重寫(xiě)的方法
  • 生成的代理對(duì)象只能轉(zhuǎn)換成 接口的不能轉(zhuǎn)換成 被代理類(lèi)
  • 代理對(duì)象只能增強(qiáng)接口中定義的方法 實(shí)現(xiàn)類(lèi)中其他和接口無(wú)關(guān)的方法是無(wú)法增強(qiáng)的
  • 代理對(duì)象只能讀取到接口中方法上的注解 不能讀取到實(shí)現(xiàn)類(lèi)方法上的注解
  • 使用方法:
public class Test1 {
    public static void main(String[] args) {
        Dinner dinner=new Person("張三");
        // 通過(guò)Porxy動(dòng)態(tài)代理獲得一個(gè)代理對(duì)象,在代理對(duì)象中,對(duì)某個(gè)方法進(jìn)行增強(qiáng)
//        ClassLoader loader,被代理的對(duì)象的類(lèi)加載器
        ClassLoader classLoader = dinner.getClass().getClassLoader();
//        Class<?>[] interfaces,被代理對(duì)象所實(shí)現(xiàn)的所有接口
        Class[] interaces= dinner.getClass().getInterfaces();
//        InvocationHandler h,執(zhí)行處理器對(duì)象,專(zhuān)門(mén)用于定義增強(qiáng)的規(guī)則
        InvocationHandler handler = new InvocationHandler(){
            // invoke 當(dāng)我們讓代理對(duì)象調(diào)用任何方法時(shí),都會(huì)觸發(fā)invoke方法的執(zhí)行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                Object proxy, 代理對(duì)象
//                Method method,被代理的方法
//                Object[] args,被代理方法運(yùn)行時(shí)的實(shí)參
                Object res=null;
               if(method.getName().equals("eat")){
                   System.out.println("飯前洗手");
                   // 讓原有的eat的方法去運(yùn)行
                   res =method.invoke(dinner, args);
                   System.out.println("飯后刷碗");
               }else{
                   // 如果是其他方法,那么正常執(zhí)行就可以了
                   res =method.invoke(dinner, args);
               }
                return res;
            }
        };
        Dinner dinnerProxy =(Dinner) Proxy.newProxyInstance(classLoader,interaces,handler);
        //dinnerProxy.eat("包子");
        dinnerProxy.drink();
    }
}
interface Dinner{
    void eat(String foodName);
    void drink();
}
class Person implements Dinner{
    private String name;
    public Person(String name) {
        this.name = name;
    }
    @Override
    public void eat(String foodName) {
        System.out.println(name+"正在吃"+foodName);
    }
    @Override
    public void drink( ) {
        System.out.println(name+"正在喝茶");
    }
}
class Student implements Dinner{
    private String name;
    public Student(String name) {
        this.name = name;
    }
    @Override
    public void eat(String foodName) {
        System.out.println(name+"正在食堂吃"+foodName);
    }
    @Override
    public void drink( ) {
        System.out.println(name+"正在喝可樂(lè)");
    }
}

3.CGlib動(dòng)態(tài)代理

cglib動(dòng)態(tài)代理模式是面向父類(lèi)

特點(diǎn):

面向父類(lèi)的和接口沒(méi)有直接關(guān)系
2.不僅可以增強(qiáng)接口中定義的方法還可以增強(qiáng)其他方法
3.可以讀取父類(lèi)中方法上的所有注解

使用實(shí)例

public class Test1 {
    @Test
    public void testCglib(){
        Person person =new Person();
        // 獲取一個(gè)Person的代理對(duì)象
        // 1 獲得一個(gè)Enhancer對(duì)象
        Enhancer enhancer=new Enhancer();
        // 2 設(shè)置父類(lèi)字節(jié)碼
        enhancer.setSuperclass(person.getClass());
        // 3 獲取MethodIntercepter對(duì)象 用于定義增強(qiáng)規(guī)則
        MethodInterceptor methodInterceptor=new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                /*Object o,  生成之后的代理對(duì)象 personProxy
                Method method,  父類(lèi)中原本要執(zhí)行的方法  Person>>> eat()
                Object[] objects, 方法在調(diào)用時(shí)傳入的實(shí)參數(shù)組
                MethodProxy methodProxy  子類(lèi)中重寫(xiě)父類(lèi)的方法 personProxy >>> eat()
                */
                Object res =null;
                if(method.getName().equals("eat")){
                    // 如果是eat方法 則增強(qiáng)并運(yùn)行
                    System.out.println("飯前洗手");
                    res=methodProxy.invokeSuper(o,objects);
                    System.out.println("飯后刷碗");
                }else{
                    // 如果是其他方法 不增強(qiáng)運(yùn)行
                    res=methodProxy.invokeSuper(o,objects); // 子類(lèi)對(duì)象方法在執(zhí)行,默認(rèn)會(huì)調(diào)用父類(lèi)對(duì)應(yīng)被重寫(xiě)的方法
                }
                return res;
            }
        };
        // 4 設(shè)置methodInterceptor
        enhancer.setCallback(methodInterceptor);
        // 5 獲得代理對(duì)象
        Person personProxy = (Person)enhancer.create();
        // 6 使用代理對(duì)象完成功能
        personProxy.eat("包子");
    }
}
class Person  {
    public Person( ) {
    }
    public void eat(String foodName) {
        System.out.println("張三正在吃"+foodName);
    }
}

原理區(qū)別:

java動(dòng)態(tài)代理是利用反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類(lèi),在調(diào)用具體方法前調(diào)用InvokeHandler來(lái)處理。

而cglib動(dòng)態(tài)代理是利用asm開(kāi)源包,對(duì)代理對(duì)象類(lèi)的class文件加載進(jìn)來(lái),通過(guò)修改其字節(jié)碼生成子類(lèi)來(lái)處理。

1、如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,默認(rèn)情況下會(huì)采用JDK的動(dòng)態(tài)代理實(shí)現(xiàn)AOP 
2、如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,可以強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP 

3、如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)了接口,必須采用CGLIB庫(kù),spring會(huì)自動(dòng)在JDK動(dòng)態(tài)代理和CGLIB之間轉(zhuǎn)換

如何強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP?
 (1)添加CGLIB庫(kù),SPRING_HOME/cglib/*.jar
 (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK動(dòng)態(tài)代理和CGLIB字節(jié)碼生成的區(qū)別?
 (1)JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類(lèi)生成代理,而不能針對(duì)類(lèi)
 (2)CGLIB是針對(duì)類(lèi)實(shí)現(xiàn)代理,主要是對(duì)指定的類(lèi)生成一個(gè)子類(lèi),覆蓋其中的方法
   因?yàn)槭抢^承,所以該類(lèi)或方法最好不要聲明成final 

兩個(gè)動(dòng)態(tài)代理的區(qū)別

  • JDK動(dòng)態(tài)代理是面向接口的,只能增強(qiáng)實(shí)現(xiàn)類(lèi)中接口中存在的方法。CGlib是面向父類(lèi)的,可以增強(qiáng)父類(lèi)的所有方法
  • JDK得到的對(duì)象是JDK代理對(duì)象實(shí)例,而CGlib得到的對(duì)象是被代理對(duì)象的子類(lèi) 生活雖然苦悶,但跑起來(lái)總是帶風(fēng)!

到此這篇關(guān)于解析動(dòng)態(tài)代理jdk的Proxy與spring的CGlib的文章就介紹到這了,更多相關(guān)動(dòng)態(tài)代理jdk的Proxy與spring的CGlib內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

富蕴县| 乌兰浩特市| 崇左市| 马尔康县| 甘孜县| 墨江| 兰考县| 丹巴县| 伊宁市| 西和县| 河北区| 临夏县| 哈密市| 吴堡县| 平南县| 车致| 恩平市| 临西县| 黔西县| 牡丹江市| 瑞丽市| 金湖县| 丹江口市| 大港区| 阿克苏市| 浑源县| 闵行区| 方山县| 长海县| 六安市| 望都县| 阿克陶县| 陵水| 平和县| 左权县| 邯郸市| 德江县| 巴彦淖尔市| 盘锦市| 大渡口区| 鸡泽县|