相比于静态代理,动态代理避免了开发者编写各个繁锁的静态代理类,只需指定一组接口及目标类对象就能动态地获取代理对象。
使用动态代理的六大步骤:
1 通过实现InvocationHandler接口来自定义自己的InvocationHandler。
2 通过Proxy类的getProxyClass方法获取代理类。
3 通过反射机制获取代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)。
4 将目标对象作为参数传入,通过构造方法获取自定义的InvocationHandler实例对象。
5 将自定义的InvocationHandler实例对象作为参数传入,通过构造方法获取代理对象。
6 代理对象调用目标方法。
JDK Proxy HelloWorld
1 package com.yao.proxy; 2 3 public interface Helloworld { 4 void sayHello(); 5 }
1 package com.yao.proxy; 2 3 import com.yao.HelloWorld; 4 5 public class HelloworldImpl implements HelloWorld { 6 public void sayHello() { 7 System.out.print("hello world"); 8 } 9 }
1 package com.yao.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class MyInvocationHandler implements InvocationHandler{ 7 private Object target; 8 public MyInvocationHandler(Object target) { 9 this.target=target; 10 } 11 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 12 System.out.println("method :"+ method.getName()+" is invoked!"); 13 return method.invoke(target,args); // 执行相应的目标方法 14 } 15 }
target属性表示代理的目标对象。InvocationHandler是连接代理对象与目标对象的自定义中间类MyInvocationHandler必须实现的接口,只有一个方法public Object invoke(Object proxy, Method method, Object[] args)。在这个方法中,Proxy通过newProxyInstance方法创建代理对象,method表示目标对象被调用的方法,args表示目标对象被调用方法的形参列表。
1 package com.yao.proxy; 2 3 import com.yao.HelloWorld; 4 import java.lang.reflect.Constructor; 5 import java.lang.reflect.InvocationHandler; 6 import java.lang.reflect.InvocationTargetException; 7 import java.lang.reflect.Proxy; 8 9 public class JDKProxyTest { 10 public static void main(String[]args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 11 // 这里有两种写法,采用复杂的一种写法,有助于理解。 12 Class<?> proxyClass= Proxy.getProxyClass(JDKProxyTest.class.getClassLoader(),HelloWorld.class); 13 final Constructor<?> cons = proxyClass.getConstructor(InvocationHandler.class); 14 final InvocationHandler ih = new MyInvocationHandler(new HelloworldImpl()); 15 HelloWorld helloWorld = (HelloWorld)cons.newInstance(ih); 16 helloWorld.sayHello(); 17 18 // 下面是简单的一种写法,本质上和上面是一样的 19 /* 20 HelloWorld helloWorld=(HelloWorld)Proxy. 21 newProxyInstance(JDKProxyTest.class.getClassLoader(), 22 new Class<?>[]{HelloWorld.class}, 23 new MyInvocationHandler(new HelloworldImpl())); 24 helloWorld.sayHello(); 25 */ 26 } 27 28 }
参考资料