java动态代理的实现及原理, 混型应用

在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方法的实现里会经过建立一个代理类,并返代理实例供咱们使用
  1. invoke方法是怎么调用的?

咱们拿的的代理类是在编译过程当中有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);  
    }  
  }
  1. invoke和add方法有什么对应关系?

实现InvocationHandler 这个接口的实例会有invoke方法,而且会执行spa

Object result = method.invoke(target, args);

经过获得执行后的返回值,add方法就在此时被真正的实例调用add方法代理

  1. 生成的代理对象是什么样子的?

编译成功后能够去$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实例就是一个混型类型,拥有多个接口功能.

相关文章
相关标签/搜索