package com.itheima.sPRing.cglibproxy;public class PersonDaoImpl{ public void savePerson() { System.out.println("save person"); }}package com.itheima.spring.cglibproxy;public class Transaction { public void beginTransaction(){ System.out.println("begin transcation"); } public void commit() { System.out.println("commit"); }}package com.itheima.spring.cglibproxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class MyInterceptor implements MethodInterceptor{ private Transaction transaction; private Object target; public MyInterceptor(Object target, Transaction transaction ) { super(); this.transaction = transaction; this.target = target; } public Object createProxy(){ //代碼增強(qiáng)類(lèi) Enhancer enhancer = new Enhancer(); enhancer.setCallback(this);//參數(shù)為攔截器 enhancer.setSuperclass(target.getClass());//生成的代理類(lèi)的父類(lèi)是目標(biāo)類(lèi) return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object[] arg2, MethodProxy arg3) throws Throwable { this.transaction.beginTransaction(); method.invoke(target); this.transaction.commit(); return null; }}package com.itheima.spring.cglibproxy;import org.junit.Test;/** * 通過(guò)cglib產(chǎn)生的是代理對(duì)象,代理類(lèi)是目標(biāo)類(lèi)的子類(lèi) * @author xx * */public class CGLibProxyTest { @Test public void testCGlib(){ Object target = new PersonDaoImpl(); Transaction transaction = new Transaction(); MyInterceptor interceptor = new MyInterceptor(target,transaction); PersonDaoImpl personDaoImpl = (PersonDaoImpl)interceptor.createProxy(); personDaoImpl.savePerson(); }}思考1、JDK動(dòng)態(tài)代理與CGLib動(dòng)態(tài)代理的比較?①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)處理。 ②JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類(lèi)生成代理,CGLIB是針對(duì)類(lèi)實(shí)現(xiàn)代理,主要是對(duì)指定的類(lèi)生成一個(gè)子類(lèi),覆蓋其中的方法 因?yàn)槭抢^承,所以該類(lèi)或方法最好不要聲明成final ③JDK代理是不需要以來(lái)第三方的庫(kù),只要要JDK環(huán)境就可以,而cglib需要第三方j(luò)ar包 ④CGLib創(chuàng)建的動(dòng)態(tài)代理對(duì)象性能比JDK創(chuàng)建的動(dòng)態(tài)代理對(duì)象的性能高,但是CGLib在創(chuàng)建代理對(duì)象時(shí)所花費(fèi)的時(shí)間卻比JDK多得多,所以對(duì)于單例的對(duì)象,因?yàn)闊o(wú)需頻繁創(chuàng)建對(duì)象,用CGLib合適,反之,使用JDK方式要更為合適一些。
2、在Spring中何時(shí)用到JDK或者CGLib實(shí)現(xiàn)的AOP?①如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,默認(rèn)情況下會(huì)采用JDK的動(dòng)態(tài)代理實(shí)現(xiàn)AOP ②如果目標(biāo)對(duì)象實(shí)現(xiàn)了接口,可以強(qiáng)制使用CGLIB實(shí)現(xiàn)AOP ③如果目標(biāo)對(duì)象沒(méi)有實(shí)現(xiàn)了接口,必須采用CGLIB庫(kù),spring會(huì)自動(dòng)在JDK動(dòng)態(tài)代理和CGLIB之間轉(zhuǎn)換
3、如何通過(guò)調(diào)試查看當(dāng)前用到的是JDK還是CGLib?CGLib的標(biāo)志:
JDK的標(biāo)志:
4、如何強(qiáng)制用CGLib實(shí)現(xiàn)AOP?①添加CGLIB庫(kù),SPRING_HOME/cglib/*.jar ②在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
5、cglib的應(yīng)用?廣泛的被許多AOP的框架使用,例如spring AOP和dynaop。hibernate使用CGLIB來(lái)代理單端single-ended(多對(duì)一和一對(duì)一)關(guān)聯(lián)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注