zoukankan      html  css  js  c++  java
  • 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()获得代理类实例;

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

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

  • 相关阅读:
    关于bind named.conf.options
    MASM 16位汇编程序几种典型的格式
    About GCC
    WebForms UnobtrusiveValidationMode 需要“jQuery”ScriptResourceMapping。
    Linux系统下的shutdown命令用于安全的关闭/重启计算机
    TreeView.ImageSet 属性
    python seaborn
    python neo4j
    Impala与Hive的比较
    pandas.resample()
  • 原文地址:https://www.cnblogs.com/eco-just/p/7855748.html
Copyright © 2011-2022 走看看