動態代理解決了方法之間的緊耦合,
IOC解決了類與類之間的緊耦合!
Cglib和jdk動態代理的區別?
1、Jdk動態代理:利用攔截器(必須實現InvocationHandler)加上反射機制生成一個代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理
2、 Cglib動態代理:利用ASM框架,對代理對象類生成的class文件加載進來,通過修改其字節碼生成子類來處理
什么時候用cglib什么時候用jdk動態代理?
1、目標對象生成了接口 默認用JDK動態代理
2、如果目標對象使用了接口,可以強制使用cglib
3、如果目標對象沒有實現接口,必須采用cglib庫,Spring會自動在JDK動態代理和cglib之間轉換
JDK動態代理和cglib字節碼生成的區別?
1、JDK動態代理只能對實現了接口的類生成代理,而不能針對類
2、Cglib是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,並覆蓋其中方法的增強,但是因為采用的是繼承,所以該類或方法最好不要生成final,對於final類或方法,是無法繼承的
Cglib比JDK快?
1、cglib底層是ASM字節碼生成框架,但是字節碼技術生成代理類,在JDL1.6之前比使用java反射的效率要高
2、在jdk6之后逐步對JDK動態代理進行了優化,在調用次數比較少時效率高於cglib代理效率
3、只有在大量調用的時候cglib的效率高,但是在1.8的時候JDK的效率已高於cglib
4、Cglib不能對聲明final的方法進行代理,因為cglib是動態生成代理對象,final關鍵字修飾的類不可變只能被引用不能被修改
Spring如何選擇是用JDK還是cglib?
1、當bean實現接口時,會用JDK代理模式
2、當bean沒有實現接口,用cglib實現
3、可以強制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
一. Cglib原理
動態生成一個要代理的子類,子類重寫要代理的類的所有不是final的方法。在子類中采用方法攔截技術攔截所有的父類方法的調用,順勢織入橫切邏輯,它比Java反射的jdk動態代理要快
Cglib是一個強大的、高性能的代碼生成包,它被廣泛應用在許多AOP框架中,為他們提供方法的攔截

最底層的是字節碼Bytecode,字節碼是java為了保證依次運行,可以跨平台使用的一種虛擬指令格式
在字節碼文件之上的是ASM,只是一種直接操作字節碼的框架,應用ASM需要對Java字節碼、class結構比較熟悉
位於ASM上面的是Cglib,groovy、beanshell,后來那個種並不是Java體系中的內容是腳本語言,他們通過ASM框架生成字節碼變相執行Java代碼,在JVM中程序執行不一定非要寫java代碼,只要能生成java字節碼,jvm並不關系字節碼的來源
位於cglib、groovy、beanshell之上的就是hibernate和spring AOP
最上面的是applications,既具體應用,一般是一個web項目或者本地跑一個程序、
使用cglib代碼對類做代理?
使用cglib定義不同的攔截策略?
構造函數不攔截方法
用MethodInterceptor和Enhancer實現一個動態代理
Jdk中的動態代理
JDK中的動態代理是通過反射類Proxy以及InvocationHandler回調接口實現的,但是JDK中所有要進行動態代理的類必須要實現一個接口,也就是說只能對該類所實現接口中定義的方法進行代理,這在實際編程中有一定的局限性,而且使用反射的效率也不高
Cglib實現
使用cglib是實現動態代理,不受代理類必須實現接口的限制,因為cglib底層是用ASM框架,使用字節碼技術生成代理類,你使用Java反射的效率要高,cglib不能對聲明final的方法進行代理,因為cglib原理是動態生成被代理類的子類
Cglib的第三方庫提供的動態代理
1 /** 2 * 動態代理: 3 * 特點:字節碼隨用隨創建,隨用隨加載 4 * 作用:不修改源碼的基礎上對方法增強 5 * 分類: 6 * 基於接口的動態代理 7 * 基於子類的動態代理 8 * 基於子類的動態代理: 9 * 涉及的類:Enhancer 10 * 提供者:第三方cglib庫 11 * 如何創建代理對象: 12 * 使用Enhancer類中的create方法 13 * 創建代理對象的要求: 14 * 被代理類不能是最終類 15 * newProxyInstance方法的參數:在使用代理時需要轉換成指定的對象 16 * ClassLoader:類加載器 17 * 他是用於加載代理對象字節碼的。和被代理對象使用相同的類加載器。固定寫法 18 * Callback:用於提供增強的代碼 19 * 他是讓我們寫如何代理。我們一般寫一個該接口的實現類,通常情況加都是匿名內部類,但不是必須的。 20 * 此接口的實現類,是誰用誰寫。 21 * 我們一般寫的都是該接口的子接口實現類,MethodInterceptor 22 */ 23 com.dynamic.cglib.Producer cglibProducer= (com.dynamic.cglib.Producer) Enhancer.create( 24 com.dynamic.cglib.Producer.class, 25 new MethodInterceptor() { 26 /** 27 * 執行被代理對象的任何方法都會經過該方法 28 * @param obj 29 * @param method 30 * @param args 31 * 以上三個參數和基於接口的動態代理中invoke方法的參數是一樣的 32 * @param proxy:當前執行方法的代理對象 33 * @return 34 * @throws Throwable 35 */ 36 @Override 37 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 38 Object returnValue=null; 39 Float money=(Float)args[0]; 40 if("saleProduct".equals(method.getName())){ 41 returnValue= method.invoke(producer,money*0.8f); 42 } 43 return returnValue; 44 } 45 } 46 ); 47 cglibProducer.saleProduct(100.0f);
JDK本身提供的動態代理實現
1 /** 2 * 動態代理: 3 * 特點:字節碼隨用隨創建,隨用隨加載 4 * 作用:不修改源碼的基礎上對方法增強 5 * 分類: 6 * 基於接口的動態代理 7 * 基於子類的動態代理 8 * 基於接口的動態代理: 9 * 涉及的類:proxy 10 * 提供者:Jdk官方 11 * 如何創建代理對象: 12 * 使用Proxy類中的newProxyInstance方法 13 * 創建代理對象的要求: 14 * 被代理類最少實現一個接口,如果沒有則不能使用 15 * newProxyInstance方法的參數:在使用代理時需要轉換成指定的對象 16 * ClassLoader:類加載器 17 * 他是用於加載代理對象字節碼的。和被代理對象使用相同的類加載器。固定寫法 18 * Class[]:字節碼數組 19 * 它是用於讓代理對象和被代理對象有相同方法。固定寫法 20 * InvocationHandler:用於提供增強的代碼 21 * 他是讓我們寫如何代理。我們一般寫一個該接口的實現類,通常情況加都是匿名內部類,但不是必須的。 22 * 此接口的實現類,是誰用誰寫。 23 */ 24 IProducer proxyProducer= (IProducer) Proxy.newProxyInstance( 25 producer.getClass().getClassLoader(), 26 producer.getClass().getInterfaces(), 27 28 new InvocationHandler() { 29 /** 30 * 作用:執行被代理對象的任何接口方法都會經過該方法 31 * @param proxy 代理對象的引用 32 * @param method 當前執行的方法 33 * @param args 當前執行方法所需的參數 34 * @return 和被代理對象有相同返回值 35 * @throws Throwable 36 */ 37 @Override 38 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 39 // 提供增強的代碼 40 // 1、獲取方法執行的參數 41 Object returnValue=null; 42 Float money=(Float)args[0]; 43 if("saleProduct".equals(method.getName())){ 44 returnValue= method.invoke(producer,money*0.8f); 45 } 46 return returnValue; 47 } 48 } 49 );
JDK和Cglib的區別: