JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 。如果想代理没有实现接口的类可以使用CGLIB包。
CGLIB是一个强大的高性能的代码生成包。它被许多AOP的框架(例如Spring AOP)使用,为他们提供方法的interception(拦截)。Hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联。EasyMock通过使用模仿(moke)对象来测试java代码的包。它们都通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
以下为模拟案例,在使用CGLIB时需引入cglib-nodep-2.1_3.jar包
定义一个HelloWorld类,注意此处是个类,而不是接口
package com.ljq.test; /** * 定义一个HelloWorld类 * * @author jiqinlin * */public class HelloWorld { public void sayHelloWorld() { System.out.println("HelloWorld!"); }}
CglibProxy类
package com.ljq.test; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy; /** * 通过Cglib实现在方法调用前后向控制台输出两句字符串 * * @author jiqinlin * */public class CglibProxy implements MethodInterceptor { //要代理的原始对象 private Object obj; public Object createProxy(Object target) { this.obj = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.obj.getClass());// 设置代理目标 enhancer.setCallback(this);// 设置回调 enhancer.setClassLoader(target.getClass().getClassLoader()); return enhancer.create(); } /** * 在代理实例上处理方法调用并返回结果 * * @param proxy * 代理类 * @param method * 被代理的方法 * @param params * 该方法的参数数组 * @param methodProxy */ public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable { Object result = null; // 调用之前 doBefore(); // 调用原始对象的方法 result = methodProxy.invokeSuper(proxy, params); // 调用之后 doAfter(); return result; } private void doBefore() { System.out.println("before method invoke"); } private void doAfter() { System.out.println("after method invoke"); } }
测试类
package com.ljq.test; public class HelloWorldTest { public static void main(String[] args) { HelloWorld helloWorld=new HelloWorld(); CglibProxy cglibProxy=new CglibProxy(); HelloWorld hw=(HelloWorld)cglibProxy.createProxy(helloWorld); hw.sayHelloWorld(); }}
运行结果为:
时间: 2024-10-12 04:24:24