您的位置:首页 > 编程语言 > Java开发

Spring AOP中两种动态代理方式

2009-10-21 14:07 513 查看
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 字节码。





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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: