重学JAVA基础(三):动态代理
1.接口
public interface Hello { public void sayHello(); }
2.实例类
public class Hello2 { public void sayHello() { System.out.println("hello world2!"); } }
public class Hello3 extends Hello2{ }
public class HelloImpl implements Hello{ @Override public void sayHello() { System.out.println("hello world!"); } }
3.JDK动态代理
ublic class JdkTest implements InvocationHandler{ private Object object; @SuppressWarnings("unchecked") public <T> T bind(Object obj){ this.object = obj; return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before sayHello"); method.invoke(object, null); System.out.println("after sayHello"); return null; } public static void main(String[] args) { JdkTest test = new JdkTest(); Hello hello = test.bind(new HelloImpl()); hello.sayHello(); } }
4.cglib动态代理
public class CglibTest implements MethodInterceptor{ private Object obj; /** * 普通接口类代理 * @author tomsnail * @date 2015年4月2日 上午10:36:10 */ public <T> T instance(T obj){ this.obj = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.obj.getClass()); enhancer.setCallback(this); return (T)enhancer.create(); } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.out.println("before sayHello"); arg3.invoke(obj, arg2); System.out.println("after sayHello"); return null; } /** * 无接口类代理 * @author tomsnail * @date 2015年4月2日 上午10:35:58 */ public <T> T instanceObject(T obj){ T t = (T)Enhancer.create(obj.getClass(),new MethodInterceptor(){ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.out.println("hello2 proxy"); return arg3.invokeSuper(arg0, arg2); } }); return t; } /** * 无接口类代理 * @author tomsnail * @date 2015年4月2日 上午10:35:58 */ public <T> T instanceSuperObject(T obj){ T t = (T)Enhancer.create(obj.getClass(),NoOp.INSTANCE);//无任何代理时,调用父类方法实现 return t; } public static void main(String[] args) { CglibTest test = new CglibTest(); Hello hello = test.instance(new HelloImpl()); hello.sayHello(); Hello2 hello2 = test.instanceObject(new Hello2());//无接口类的动态代理 hello2.sayHello(); Hello2 hello3 = test.instanceSuperObject(new Hello3());//子类没有重写父类方法的动态代理 hello3.sayHello(); } }
5.小小总结一下
JDK的动态代理只能通过接口进行处理,如果没有接口的,会很难处理。cglib没有这一限制。
还有就是性能,我看见一篇网上已经有了对比,在jdk7/8与cglib相比,反而jdk的性能很好,见http://www.cnblogs.com/haiq/p/4304615.html