Spring AOP中两种动态代理方式

本文介绍了Java反射机制和cglib库的原理及应用。通过对比JDK反射机制需要实现接口的方式,阐述了cglib如何在不需要接口的情况下生成代理类,并通过实际案例展示了cglib的具体使用方法。

1. JDk 反射机制

实现java.lang.reflect.InvocationHandler接口,复写其中的invoke方法。

生成代理核心方法是:

newProxyInstance (obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), InvocationHandler invocationHandler);

从 obj.getClass().getInterfaces() 可以看出,如果直接用 JDK 的反射需要创建接口,比较麻烦。

2.cglib

cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。cglib封装了asm,可以在运行期动态生成新的class。asm 是一个强大的 Java 字节码生成框架,和 BCEL 或者 SERP 很类似,但是小很多,可以动态修改 java 字节码。

image

cgLib 可以不用接口,它底层调用asm 动态生成一个代理类去覆盖父类中非 final 的方法,然后实现 MethodInterceptor 接口的 intercept 方法,这样以后直接调用重写的方法,比 JDK 要快。但是加载 cglib 消耗时间比直接 JDK 反射时间长,开发的过程中,如果是反复动态生成新的代理类推荐用 JDK 自身的反射,反之用 cglib。

顺便了解了一下cglib在Hibernate延迟加载中的应用:

先看如下语句,

newProxyInstance (obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), InvocationHandler invocationHandler);

在session.load()执行时,并没有查询数据库,只有在执行user.getName()方法时才真正去获取name属性的值,这就是延迟加载的应用,通过这种方式可以降低系统资源的耗费,从而提升效率。

在执行session.load()方法时,返回的User对象其实是User类的一个代理对象,在Hibernate中通过使用cglib来实现动态构造一个目标对象的代理对象,并在代理类对象中包含目标对象的属性和方法,而且所有属性均被复制为null。当调用user.getName()方法,此时Hibernate通过cglib的回调机制,实际上调用CGLIB$CALLBACK_0.getName()方法,当调用该方法时,Hibernate会检查CGLIB$CALLBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName()方法,如果为空,则会到数据库进行查询,并将查询到的结果构造为目标对象复制到CGLIB$CALLBACK_0.target属性中。

以下转载一个实例,说明cglib的使用:

原文链接:http://www.blogjava.net/Good-Game/archive/2007/11/05/158192.html

/** *使用类 */ public class MyClass { public void method() { System.out.println("MyClass.method()"); } public void method2() { System.out.println("MyClass.method2()"); } } /** *使用代理 */ import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodInterceptor; public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); //在这代理了 enhancer.setSuperclass(MyClass.class); enhancer.setCallback( new MethodInterceptorImpl() ); // 创造 代理 (动态扩展了MyClass类) MyClass my = (MyClass)enhancer.create(); my.method(); } private static class MethodInterceptorImpl implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println(method); proxy.invokeSuper(obj, args); return null; } } } /** *添加方法过滤 */ import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.NoOp; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; public class Main2 { public static void main(String[] args) { Callback[] callbacks = new Callback[] { new MethodInterceptorImpl(), NoOp.INSTANCE }; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyClass.class); enhancer.setCallbacks( callbacks ); //添加 方法过滤器 返回1为不运行 2 为运行 enhancer.setCallbackFilter( new CallbackFilterImpl() ); MyClass my = (MyClass)enhancer.create(); my.method(); my.method2(); } private static class CallbackFilterImpl implements CallbackFilter { public int accept(Method method) { if ( method.getName().equals("method2") ) { return 1; } else { return 0; } } } private static class MethodInterceptorImpl implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println(method); return proxy.invokeSuper(obj, args); } } }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值