JDK动态代理:
a、先定义一个接口,这个接口中的方法是“目标方法”
package com.brickworkers; public interface Sky { public void rain(); }
b、接着写一个这个接口的具体实现:
package com.brickworkers; public class SkyImpl implements Sky{ @Override public void rain() { System.out.println("it`s raining"); } }
c、如果要完成动态代理,首先需要定义一个InvocationHandler接口的子类:
package com.brickworkers; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyInvocationHandler implements InvocationHandler { //目标对象 private Object obj = null; //获取目标对象的代理对象 public Object getProxy(Object obj){ this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); } //控制执行目标对象的方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("目标对象方法执行之前"); Object result = method.invoke(obj, args); System.out.println("目标对象方法执行之后"); return result; } }
d:JDK动态代理测试类:
package com.brickworkers; public class ProxyTest { public static void main(String[] args) { //实例化InvocationHandler MyInvocationHandler myInvocationHandler = new MyInvocationHandler(); //生产代理对象 Sky sky = (Sky) myInvocationHandler.getProxy(new SkyImpl()); sky.rain(); } } //执行结果: 目标对象方法执行之前 // it`s raining // 目标对象方法执行之后
为什么JDK动态代理只能局限于接口呢?查阅了一些技术文档和JDK动态代理的源码,发现在反编译产生的proxyTest.class中,类的定义如下:
import dynamic.proxy.UserService; import java.lang.reflect.*; public final class $ProxyTest extends Proxy implements Sky { ...... }
从反编译的源码可以看出,proxyTest继承了Proxy,然而在Java中只支持单继承,但是可以实现多个接口,所以JDK动态代理只能局限于接口。
那么JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,要实现动态代理要怎么办呢?这个时候就需要CGLib动态代理了。
CGLib动态代理:
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有分类方法的调用,顺势织入和横切逻辑。-http://blog.csdn.net/yakoo5/article/details/9099133/
a、定义一个目标对象:
package com.brickworkers; public class Color { public void showColor(){ System.out.println("red"); } }
b、如果要完成动态代理,首先需要定义一个MethodInterceptor接口的子类:
package com.brickworkers; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class MyCglib implements MethodInterceptor { //目标对象 private Object obj = null; public Object getProxy(Object obj){ this.obj = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("目标对象方法执行之前"); Object result = methodProxy.invoke(obj, args); System.out.println("目标方法执行之后"); return result; } }
c、CGLib动态代理测试类:
package com.brickworkers; public class CGLibTest { public static void main(String[] args) { MyCglib myCglib = new MyCglib(); Color color = (Color) myCglib.getProxy(new Color()); color.showColor(); } } //执行结果:目标对象方法执行之前 // red // 目标方法执行之后
因为CGLib动态代理是创建一个子类来实现的,那么对于继承的定义,final类是无法进行代理的。