老王讲自制RPC框架.(二.动态代理)

(#简介)

什么是动态代理?动态代理是实现阶段不关心代理是谁,而在运行阶段才指定代理对象是哪一个,动态代理在做框架方面使用非常
广泛,比如spring的aop,其核心就是采用动态代理机制,下面让我们来看看如何实现一个动态代理模式

(#实现)

首先我们来定义一个接口

public interface ICar {
    void run(String name);
}

然后我们来定义一个实现类

public class Car implements ICar {
    public void run(String name) {
        System.out.println(name+"car is running");
    }
}

接下来我们来实现一个通用的动态的代理工具类

public class ObjectProxy{

    public <T> T create(final T t) {
        return (T) Proxy.newProxyInstance(ObjectProxy.class.getClassLoader(),
                t.getClass().getInterfaces(), new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              //before invoke return method.invoke(t, args);
              //after invoke } }); } }

在这个工具类中我们使用到了泛型来使方法变得更通用,如果对于泛型缺乏理解的话请看这个博客:https://segmentfault.com/a/1190000002646193

最后我们来看一下调用:

  public static void main(String[]args){
  
        ICar car = new Car();
        ObjectProxy carProxy = new ObjectProxy();
        ICar proxyCar = carProxy.create(car);
        proxyCar.run("benchi ");
    }

如果不出意外的话运行main方法会出现: benchi car is running.   当然使用动态代理的最厉害的点就是你可以在调用这个方法的时候可以做一些before和after的事情

这样可操作性就很大,对于一些功能特别适用

(#)拓展 

 在反射方面介绍一个比较强大的库cglib,在某些特定的场景下使用fast反射是必须的,jdk的普通代理有一点是比较搓的,就是只能代理实现的接口,而不能代理自身的方法

这个时候想要实现动态代理的功能就需要使用到cglib了,好,下面举个栗子:

首先扩展原有实现类:增加一个自身的方法nRun,下面我们来实现它的代理

public class Car implements ICar {
    public void run(String name) {
        System.out.println(name+"car is running");
    }
    public void nRun(String name){
        System.out.println(name+" 我是自身的run");
    }
}

  

第一种实现:

public class FastProxy {
    public <T> T create(final T t) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(t.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                return methodProxy.invoke(t,objects);
            }
        });
        return (T) enhancer.create();
    }
}

第二种实现:

public class FastProxy {
    public <T> T create(final T t) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(t.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                FastClass fastClass = FastClass.create(t.getClass());
                FastMethod fastMethod = fastClass.getMethod(method.getName(),method.getParameterTypes());
                return fastMethod.invoke(t,objects);

            }
        });
        return (T) enhancer.create();
    }
}

在main方法的调用上是没什么区别的,这样我们就实现了对于自身方法的动态代理.