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

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

示例:

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();
    }

}

执行结果:

----- before -----
----- add -----
----- after -----
----- before -----
----- add 2-----
----- after -----

代理实现过程中的问题说明:
1. 这个代理对象是由谁且怎么生成的?

 Proxy.newProxyInstance方法的实现里会通过创建一个代理类,并返代理实例供我们使用
  1. invoke方法是怎么调用的?

我们拿的的代理类是在编译过程中有jdk自动生成的. 类里会实现各个接口的方法,实现的方法里会调用invoke,例如:

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方法,并且会执行

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

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

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

编译成功后可以去$Proxy0.class文件查看内容

总结:
一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
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实例就是一个混型类型,拥有多个接口功能.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值