Spring AOP中两种动态代理方式
2009-10-21 14:07
513 查看
1. JDk 反射机制
实现java.lang.reflect.InvocationHandler接口,复写其中的invoke方法。
生成代理核心方法是:
从 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延迟加载中的应用:
先看如下语句,
在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
实现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); } } }
相关文章推荐
- Java 动态代理实现的两种方式
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 设计模式(3)-结构型-代理模式(proxy)以及java动态代理的两种方式
- java动态代理的两种方式
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 动态代理的两种实现方式(JDK/Cglib)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring的两种代理方式:JDK动态代理和CGLIB动态代理
- 设计模式(3)-结构型-代理模式(proxy)以及java动态代理的两种方式
- 动态代理的两种实现方式
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理-转载
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- 10077---Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
- Java实现动态代理的两种方式
- spring实现AOP的两种方式以及实现动态代理方式
- 动态代理 两种方式
- 设计模式(3)-结构型-代理模式(proxy)以及java动态代理的两种方式
- spring实现AOP的两种方式以及实现动态代理方式
- 动态代理的两种方式jdk和cglib