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(){
//代碼增強類
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);//參數為攔截器
enhancer.setSuperclass(target.getClass());//生成的代理類的父類是目標類
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;
/**
* 通過cglib產生的是代理對象,代理類是目標類的子類
* @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動態代理與CGLib動態代理的比較?①Java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。 而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。 ②JDK動態代理只能對實現了接口的類生成代理,CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法 因為是繼承,所以該類或方法最好不要聲明成final ③JDK代理是不需要以來第三方的庫,只要要JDK環境就可以,而cglib需要第三方jar包 ④CGLib創建的動態代理對象性能比JDK創建的動態代理對象的性能高,但是CGLib在創建代理對象時所花費的時間卻比JDK多得多,所以對于單例的對象,因為無需頻繁創建對象,用CGLib合適,反之,使用JDK方式要更為合適一些。
2、在Spring中何時用到JDK或者CGLib實現的AOP?①如果目標對象實現了接口,默認情況下會采用JDK的動態代理實現AOP ②如果目標對象實現了接口,可以強制使用CGLIB實現AOP ③如果目標對象沒有實現了接口,必須采用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換
3、如何通過調試查看當前用到的是JDK還是CGLib?CGLib的標志:
JDK的標志:
4、如何強制用CGLib實現AOP?①添加CGLIB庫,SPRING_HOME/cglib/*.jar ②在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
5、cglib的應用?廣泛的被許多AOP的框架使用,例如spring AOP和dynaop。hibernate使用CGLIB來代理單端single-ended(多對一和一對一)關聯。
新聞熱點
疑難解答