转载自:http://langyu.iteye.com/blog/410071
http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
1. InvocationHandler:该接口中仅定义了一个invoke方法。每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
1: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{...}
第一个参数obj一般是指要代理的类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
2. Proxy:该类的作用就是用来动态创建一个代理对象的类,其中主要包含以下方法:
1: public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{…}
2: //获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组.
1: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{…}
2: //返回代理类的一个实例,返回后的代理类可以当作被代理类使用.
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载。
interfaces: 一个Interface对象的数组,表示的是要给需要代理的对象提供一组什么接口,如果提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样就能调用这组接口中的方法了。
h: 一个InvocationHandler对象,表示的是当这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
Proxy.newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下几件事.
(1)根据参数loader和interfaces调用getProxyClass(loader, interfaces)创建代理类$Proxy. $Proxy0类实现了interfaces的接口,并继承了Proxy类.
(2)实例化$Proxy0并在构造方法中把loader传过去, 接着$Proxy0调用父类Proxy的构造器,为h赋值。接着把得到的$Proxy0实例强制转换成代理类. 当执行代理类的方法时,就调用了$Proxy0类中的方法.在执行代理类方法中,调用父类Proxy中的h的invoke()方法.即InvocationHandler.invoke()。
示例:
1: package com.zero;
2:
3: public interface IHello {
4: void say();
5: }
1: package com.zero;
2:
3: public class HelloImpl implements IHello {
4:
5: @Override
6: public void say() {
7: // TODO Auto-generated method stub
8: System.out.println("Say hello!");
9: }
10: }
1: package com.zero;
2:
3: import java.lang.reflect.InvocationHandler;
4: import java.lang.reflect.Method;
5:
6: public class JDKProxyHandler implements InvocationHandler {
7: // 这个就是我们要代理的真实对象
8: private Object realObject;
9:
10: // 构造方法,给我们要代理的真实对象赋初值
11: public JDKProxyHandler(Object target) {
12: this.realObject = target;
13: }
14:
15: @Override
16: public Object invoke(Object proxy, Method method, Object[] args)
17: throws Throwable {
18: // TODO Auto-generated method stub
19: System.out.println("jdk...invoke() begin");
20: System.out.println(method);
21: Object result = method.invoke(realObject, args);
22: System.out.println("jdk...invoke() end");
23: return result;
24: }
25: }
1: package com.zero;
2:
3: import java.lang.reflect.Proxy;
4:
5: public class JDKProxyTest {
6:
7: public static void main(String[] args) {
8: // TODO Auto-generated method stub
9: HelloImpl impl = new HelloImpl();
10: // 这里把handler与impl新生成的代理类相关联
11: JDKProxyHandler handler = new JDKProxyHandler(impl);
12: // 获得代理类($Proxy0 extends Proxy implements IHello)的实例.
13: IHello hello = (IHello) Proxy.newProxyInstance(impl.getClass()
14: .getClassLoader(), impl.getClass().getInterfaces(), handler);
15: // 这里无论访问哪个方法,都是会把请求转发到handler.invoke
16: hello.say();
17: System.out.println(hello.getClass());
18: //class com.sun.proxy.$Proxy0
19: }
20: }
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,它的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
示例:
1: package com.zero;
2:
3: import java.lang.reflect.Method;
4:
5: import org.springframework.cglib.proxy.Enhancer;
6: import org.springframework.cglib.proxy.MethodInterceptor;
7: import org.springframework.cglib.proxy.MethodProxy;
8:
9: public class CGlibProxyHander implements MethodInterceptor {
10: private Object target;
11:
12: // target不必须使用接口
13: public Object createProxyInstance(Object target) {
14: this.target = target;
15: Enhancer enhancer = new Enhancer();
16: // 实际上是继承了目标类,覆盖目标类所有非final方法,再基础上添加新的代码
17: // 使用Enhancer可以对任意类生成代理类,
18: // 只要enhancer.setSuperclass(this.target.getClass());
19: // 其实质是代理类是目标类的子类。
20: enhancer.setSuperclass(this.target.getClass());
21: enhancer.setCallback(this);
22: return enhancer.create();
23: }
24:
25: // 从参数构成上,intercept的输入参数比invoke多1个,其实前3个参数对象的含义与invoke的含义是相同的
26: // 第一个参数表示调用方法来自哪个对象;
27: // 第二个参数表示调用方法的Method对象;
28: // 第三个参数表示此次调用的输入参数列表;
29: // 多出来的参数是MethodProxy 类型的,它应该是cglib生成用来代替Method对象的一个对象,
30: // 使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升
31: @Override
32: public Object intercept(Object object, Method method, Object[] args,
33: MethodProxy methodProxy) throws Throwable {
34: Object result = null;
35: System.out.println("CGlib代理 " + method.getName() + "()方法");
36: result = methodProxy.invoke(this.target, args);
37: return result;
38: }
39: }
1: package com.zero;
2:
3: import java.lang.reflect.Proxy;
4:
5: public class CGlibProxyTest {
6:
7: public static void main(String[] args) {
8: // TODO Auto-generated method stub
9: HelloImpl impl = new HelloImpl();
10: CGlibProxyHander hander = new CGlibProxyHander();
11:
12: IHello hello = (IHello) hander.createProxyInstance(impl);
13: hello.say();
14: System.out.println(hello.getClass());
15: // class com.sun.proxy.$Proxy0
16: }
17: }