先说说两者的区别
jdk动态代理是java的标准api , 被代理的类必须实现一个或者多个接口,然后根据接口和实现类动态创建代理类,所生成的代理类是java.lang.reflect.Proxy的子类,并且也是实现类的子类(这块可能有点绕)
cglib动态代理是依靠cglib库的api ,被代理的类不用实现接口,它是以生成被代理类的子类的方法来生成代理类的。相比JDK动态代理的优势在于被代理的类不用实现任何接口就可以代理。这里要注意被代理的类不能是final。
下面先上被代理类的代码
接口
package net; public interface ISay { public void say(); }
实现类
package net; public class Person implements ISay { @Override public void say() { System.out.println("person say......."); } }
下面让我们来看看JDK如何给这个类动态生成代理类,首先写一个代理的处理类,实现java.lang.reflect.InvocationHandler接口
看代码
package jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import net.ISay; public class MyInvocationHandler implements InvocationHandler { //被代理的类 private ISay target; public MyInvocationHandler(ISay target) { this.target = target; } /** * * @param proxy 生成的代理对象,这里要注意这个参数不是被代理类。 * 这个参数目前没有发现其作用,欢迎知道的拍砖 * @param method 被代理对象的原始方法 * @param args 方法调用所需要的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object result = method.invoke(target, args); System.out.println("end"); return result; } }
测试类
package jdk; import java.lang.reflect.Proxy; import net.ISay; import net.Person; public class Run { public static void main(String[] args) { Person p=new Person(); MyInvocationHandler mih=new MyInvocationHandler(p); ISay proxyPerson=(ISay) Proxy.newProxyInstance(Run.class.getClassLoader(), new Class[]{ISay.class}, mih); proxyPerson.say(); } }
运行的测试结果
before
person say.......
end
package cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public abstract class CglibProxy implements MethodInterceptor { @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> t) { Enhancer e = new Enhancer(); //设置代理的类的class e.setSuperclass(t); //设置要处理代理类方法的处理类 e.setCallback(this); return (T) e.create(); } /** * * @param obj 生成的代理对象 * @param method 被代理类的原始方法 * @param objs 调用方法的参数 * @param mp 代理类方法的对象,包含被代理类的原始方法 * @return * @throws Throwable */ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { before(); //这里调用父类原始的方法,也就是被代理对象的原始方法 Object result = mp.invokeSuper(obj, args); end(); return result; } public abstract void before(); public abstract void end(); }
这个生成代理的类,只能生成带有无参数构造方法的类,并且被代理的类不能是final
测试方法
package cglib; import net.Person; public class Run { public static void main(String[] args) { // 用内部类实现 CglibProxy cp = new CglibProxy() { @Override public void before() { System.out.println("before"); } @Override public void end() { System.out.println("end"); } }; Person p = cp.getProxy(Person.class); p.say(); } }
我们来看看控制台输出了什么
before
person say.......
end