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)注