java之Spring(AOP)前奏-动态代理设计模式(下)

在上一章我们看到了,新增的三种类都能实现对原始功能类进行添加功能的事务处理,这三种类就是一个代理。

但是这种代理是写死的,怎样实现对任意接口添加自定义的代理呢?

我们先来看一下之前的代理实现:

 1 public class Impeat {
 2     private InterfaceDo todo;
 3     public Impeat(InterfaceDo todo) {
 4         super();
 5         this.todo = todo;
 6     }
 7     public void dothings() {
 8         todo.dosomething();
 9         System.out.println("我要吃饭了啊--------");
10     }
11 }

因为这里我们的代理不需要再被其他代理引用,所以就不需要实现InterfaceDo接口,自然内部方法也是可以自定义,没有必要

遵循InterfaceDo的方法定义,为了避免混淆,我们将其改为了dothings(),由于代理类都是这样的一个书写模式:定义成员变量、

构造函数为成员变量赋值为代理对象、自定义方法实现对代理对象方法的调用。我们索性定义一个接口,以后所有的代理类都按

照统一模式来写,在JDK中就定义了这样的一个接口InvocationHandler,我们的代理类都实现这个接口,遵循它的书写方式,

下面我们再来看看代理类里面的元素:

InterfaceDo:需要代理对象的实现接口;

todo:需要代理的对象;

红字:为代理对象添加的功能实现;

todo.dosomething():代理对象的原始功能。

既然要实现动态代理,那么这个代理实现的部分源码,就不能写死了(被代理对象的接口、被代理的对象以及被代理对象内部的

方法),接口我们可以自定义,被代理对象我们可以new出来,但是被代理对象内部的方法是不确定的,A代理对象可能是A方法,

B代理对象可能是B方法,C代理对象可能是C方法。

所以,我们要动态获取代理对象的内部方法就得通过反射来获得。

被代理对象的方法怎么获得呢?由于被代理对象是实现了接口的,被代理对象的内部方法必定也是重写自接口的定义方法的。那么

我们就可以从接口入手,获取接口的方法定义。

来看看JDK的实现:

public class Handlerimp implements InvocationHandler {
    private Object obj;
    public Handlerimp(Object obj) {
        super();
        this.obj = obj;
    }
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("-----我要实现新的功能-----");
        Object returnValue = method.invoke(obj, args);
        return returnValue;
    }
}

是不是很眼熟,对,这个和我们之前的静态代理实现模式一样。只不过底层已经用反射帮我们获得了被代理对象obj的方法method

以及方法的参数数组,然后通过被代理对象、方法、参数三者来执行被代理对象的方法-------method.invoke(proxy,args)。

接下来,我们实例化一个该代理类的实例:

public class Testperson {
    public static void main(String[] args) {
        InterfaceDo a = new Persontodo();
        Handlerimp handler =new Handlerimp(a);
        ClassLoader loader = a.getClass().getClassLoader();
        Class[] interfaces = a.getClass().getInterfaces();
        InterfaceDo subject = (InterfaceDo) Proxy.newProxyInstance(loader, interfaces, handler);
        subject.dosomething();
        subject.dothing();
    }
}

 

我们可以看到,JDK中通过Proxy类的静态方法newProxyInstance()获得代理类实例;

该方法实现了对被代理对象所有方法的遍历,因此实现了对被代理对象所有方法的功能添加。

之后,我们就可以调用代理类的方法了。

转载于:https://www.cnblogs.com/eco-just/p/7855748.html

你可能感兴趣的:(设计模式,java)