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(多对一和一对一)关联。
新闻热点
疑难解答