目前的Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。即如果想对一个类进行动态代理,那么这个类首先要继承了某个接口,否则就无法对其进行代理。
CGLIB就可以对一个普通java类进行代理,不需要其实现任何接口。CBLIB的实现采用非常底层的字节码技术,为一个类动态生成一个子类,并在子类中覆盖其父类所有的非final的方法,对其进行拦截,以实现动态代理的效果,是对JDK动态代理的一个很好的补充。
我写了个小例子,HelloWorld类为业务方法类(没有实现任何接口),其中包括一个有返回值和无返回值的两个方法,CglibProxy为动态代理类,在这个类中可以实现对HelloWorld类方法的拦截,可以把诸如权限校验、记录日志这样的横切性问题在这里进行处理。
业务实现类:
package com.why.cglib.proxy; /** * 业务实现类 * @author why * */ public class HelloWorld{ public void sayHello() { System.out.println("执行了 sayHello()"); } public String sayHelloWithReturnValue() { String str = "HelloWorld!"; System.out.println("执行了 sayHelloWithReturnValue()"); return str; } }
动态代理类:
package com.why.cglib.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 动态代理类 * @author why * */ public class CglibProxy implements MethodInterceptor{ private Object targetObject;//要代理的目标对象 public Object newProxy(Object targetObject) { this.targetObject = targetObject ; Enhancer enhancer = new Enhancer();//该类用于生成代理对象 enhancer.setSuperclass(this.targetObject.getClass());//设置父类 enhancer.setCallback(this);//设置回调对象为本身 return enhancer.create();//通过字节码技术动态创建子类实例 } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object result = null;; doBefore(); try{ result = methodProxy.invokeSuper(proxy, args);//调用原始对象的方法 doAfter(); }catch (Exception e) { e.printStackTrace(); doWhenException(); }finally{ doFinally(); } return result; } private void doBefore() { System.out.println("before method invoke!"); } private void doAfter() { System.out.println("after method invoke!"); } private void doWhenException() { System.out.println("WhenException method invoke!"); } private void doFinally() { System.out.println("Finally method invoke!"); } }
测试类:
package com.why.cglib.proxy; public class Test { /** * CGLIB 动态代理 * * @param args */ public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); HelloWorld proxy = (HelloWorld)cglibProxy.newProxy(new HelloWorld()); proxy.sayHello(); System.out.println("\n---------------------------------\n"); String str = proxy.sayHelloWithReturnValue(); System.out.println("str = " + str); } }