在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另外一个则是 Proxy(Class),这一个类和接口是实现咱们动态代理所必须用到的。java
示例:数组
public class DynamicProxyTest { interface UserService { public abstract void add(); } interface UserService2 { public abstract void add2(); } static class UserServiceImpl implements UserService, UserService2 { public void add() { System.out.println("----- add -----"); } public void add2() { System.out.println("----- add 2-----"); } } static class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { super(); this.target = target; } public Object getProxy() { /** * Thread.currentThread().getContextClassLoader(: 一个ClassLoader对象,定义了由哪一个ClassLoader对象来对生成的代理对象进行加载 * arget.getClass().getInterfaces(): 一个Interface对象的数组,表示的是我将要给我须要代理的对象提供一组什么接口,若是我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 * this: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪个InvocationHandler对象上 */ return Proxy.newProxyInstance(Thread.currentThread() .getContextClassLoader(), target.getClass().getInterfaces(), this); } /** * proxy: 咱们所代理的那个真实对象 * method: 咱们所要调用真实对象的某个方法的Method对象 * args: 调用真实对象某个方法时接受的参数 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("----- before -----"); Object result = method.invoke(target, args); System.out.println("----- after -----"); return result; } } /** * @param args */ public static void main(String[] args) { UserService userService = new UserServiceImpl(); MyInvocationHandler invocationHandler = new MyInvocationHandler( userService); UserService proxy = (UserService) invocationHandler.getProxy(); proxy.add(); ((UserService2)proxy).add2(); } }
执行结果:markdown
----- before ----- ----- add ----- ----- after ----- ----- before ----- ----- add 2----- ----- after -----
代理实现过程当中的问题说明:
1. 这个代理对象是由谁且怎么生成的?函数
Proxy.newProxyInstance方法的实现里会经过建立一个代理类,并返代理实例供咱们使用
咱们拿的的代理类是在编译过程当中有jdk自动生成的. 类里会实现各个接口的方法,实现的方法里会调用invoke,例如:this
public final void add() throws { try { this.h.invoke(this, m3, null); return; } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } }
实现InvocationHandler 这个接口的实例会有invoke方法,而且会执行spa
Object result = method.invoke(target, args);
经过获得执行后的返回值,add方法就在此时被真正的实例调用add方法代理
编译成功后能够去$Proxy0.class文件查看内容code
总结:
一个典型的动态代理建立对象过程可分为如下四个步骤:
一、经过实现InvocationHandler接口建立本身的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
二、经过为Proxy类指定ClassLoader对象和一组interface建立动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
三、经过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
四、经过构造函数建立代理类实例,此时需将调用处理器对象做为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象建立过程,Proxy类中的newInstance方法封装了2~4,只需两步便可完成代理对象的建立。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))对象
动态代理与混型的应用继承
示例代码:
public class DynamicProxyMixin { class TwoTuple<A, B> { public A first; public B second; public TwoTuple(A a, B b) { this.first = a; this.second = b; } } interface TimeStamped { long getStamped(); } static class TimeStampedImpl implements TimeStamped { private final long date; public TimeStampedImpl() { date = new Date().getTime(); } public long getStamped() { return date; } } interface SerialNumbered { long getSerialNumbered(); } static class SerialNumberedImpl implements SerialNumbered { private static long counter = 1; private final long serialNumber = counter++; public long getSerialNumbered() { return serialNumber; } } interface Basic { void set(String val); String get(); } static class BasicImpl implements Basic { private String value; public void set(String val) { value = val; } public String get() { // TODO Auto-generated method stub return value; } } static class MixinProxy implements InvocationHandler { Map<String, Object> delegateByMethodMap; private MixinProxy(TwoTuple<Object, Class<?>> ...pairs) { delegateByMethodMap = new HashMap<String, Object>(); for (TwoTuple<Object, Class<?>> pair : pairs) { for (Method method : pair.second.getMethods()) { String methodName = method.getName(); if (!delegateByMethodMap.containsKey(methodName)) { delegateByMethodMap.put(methodName, pair.first); } } } } public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable { String methodName = method.getName(); return method.invoke(delegateByMethodMap.get(methodName), arg2); } public static Object newInstance(TwoTuple<Object, Class<?>> ...pairs){ Class[] interfaces = new Class[pairs.length]; for (int i = 0, count = interfaces.length; i < count; i++) { interfaces[i] = (Class) pairs[i].second; } ClassLoader loader = pairs[0].first.getClass().getClassLoader(); return Proxy.newProxyInstance(loader, interfaces, new MixinProxy(pairs)); } } /** * @param args */ public static void main(String[] args) { Object proxyObject = MixinProxy.newInstance(new TwoTuple(new BasicImpl(), Basic.class), new TwoTuple(new TimeStampedImpl(), TimeStamped.class), new TwoTuple(new SerialNumberedImpl(), SerialNumbered.class)); Basic b = (Basic) proxyObject; SerialNumbered serialNumbered = (SerialNumbered) proxyObject; TimeStamped timeStamped = (TimeStamped) proxyObject; b.set("hello"); System.out.println(b.get()); System.out.println(serialNumbered.getSerialNumbered()); System.out.println(timeStamped.getStamped()); } }
执行结果:
hello 1 1494841280897
经过动态代理获得的proxyObject实例就是一个混型类型,拥有多个接口功能.