代理对象:ProxyFactory
package com.cglib; 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 ProxyFactory implements MethodInterceptor{ private Object target;//维护一个目标对象 public ProxyFactory(Object target) { this.target = target; } //为目标对象生成代理对象 public Object getProxyInstance() { //工具类 Enhancer en = new Enhancer(); //设置父类 en.setSuperclass(target.getClass()); //设置回调函数 en.setCallback(this); //创建子类对象代理 return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开启事务"); // 执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("关闭事务"); return null; } }
测试类:TestProxy
package com.cglib; import org.junit.Test; public class TestProxy { @Test public void testCglibProxy(){ //目标对象 UserDao target = new UserDao(); System.out.println(target.getClass()); //代理对象 UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance(); System.out.println(proxy.getClass()); //执行代理对象方法 proxy.save(); } }
输出结果
class com.cglib.UserDao class com.cglib.UserDao$$EnhancerByCGLIB$$552188b6 开启事务 保存数据 关闭事务
五、总结
静态代理实现较简单,只要代理对象对目标对象进行包装,即可实现增强功能,但静态代理只能为一个目标对象服务,如果目标对象过多,则会产生很多代理类。
JDK动态代理需要目标对象实现业务接口,代理类只需实现InvocationHandler接口。
动态代理生成的类为 lass com.sun.proxy.$Proxy4,cglib代理生成的类为class com.cglib.UserDao
EnhancerByCGLIB
EnhancerByCGLIB
552188b6。
静态代理在编译时产生class字节码文件,可以直接使用,效率高。
动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。
cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。
六、静态代理与动态代理的区别
静态代理:硬编码、手动注入,手动拿到目标对象的引用,手动调用代理目标对象的方法
动态代理:具有更强的扩展性,自动注入,自动生成一个新的类(同一个继承体系)
特征: 拿到代理目标对象的引用,实现功能增强
七、JDK动态代理生成$Proxy0.java对象的步骤
1、动态生成源码.java文件
2、Java文件输出到磁盘,保存到P r o x y 0. j a v a 3 、 把 . j a v a 文 件 编 译 为 Proxy0.java 3、把.java文件编译为Proxy0.java3、把.java文件编译为Proxy0.class文件
4、把生成.class文件加载到JVM中
5、返回新的代理对象
Java三种代理模式:静态代理、动态代理和cglib代理