zoukankan      html  css  js  c++  java
  • java之Spring(AOP)前奏-动态代理设计模式(上)

    我们常常会遇到这样的事,项目经理让你为一个功能类再加一个功能A,然后你加班为这个类加上了功能A;

    过了两天又来了新需求,再在A功能后面加上一个新功能B,你加班写好了这个功能B,加在了A后面;又过

    了几天天,项目经理说这两个新加的功能顺序需要调换一下,然后你找到一个礼拜之前的写的源代码,看了

    一遍想起来当时是怎么实现的了,这部分是功能A,那部分是功能B,然后巴拉巴拉换了顺序。看到这是不是

    觉得很烦,动不动就要在源码上加新功能,完了又要在源码上换新功能的顺序,那么一大坨源码,还好是自

    己写的源码,理解起来很快,操作起来也很快,万一是别人的源码,别人的编程习惯可能和自己的不一样,

    看他的源码,又要多花点时间,真是卷铺盖走人的心都有了。

    这个时候,我们就可以用代理来为源码有序地添加新功能。

    1.定义一个接口

    public interface InterfaceDo {
        public void dosomething();
    }

    2.定义原始功能类

    public class Persontodo implements InterfaceDo {
        public void dosomething() {
            System.out.println("要干什么呢--------");
        }
    }

    我们可以看到,这个类实现了之前的接口, 但是只做一件事:思考人生!

    3.定义额外功能类,并实现对原始功能的调用

    public class Impeat implements InterfaceDo {
        private InterfaceDo todo;
        public Impeat(InterfaceDo todo) {
            super();
            this.todo = todo;
        }
        public void dosomething() {
            todo.dosomething();
            System.out.println("我要吃饭了啊--------");
        }
    }

    我们看到这个类引入了一个成员变量,类型为InterfaceDo(接口)类型,

    构造函数实现为成员变量赋值,那么当我们实例化这个类的时候,它内部的成员变量是指向传入的参数对象的实例的。

    Persontodo a = new Persontodo();

    Impeat b  = new Impeat(a);

    那么,b.dosomething()这个方法实现的功能是:先执行实例化时候传进来的参数todo的todo.dosomething()方法,然后

    再执行语句System.out.println("我要吃饭了啊------------");

    在上面的例子由于传进来的参数是a,那么b.dosomething()就同等于以下两步操作:

    ①a.dosomething();

    ②System.out..println("我要吃饭了啊------------");

    结果控制台打印输出:

    要干什么呢--------

    我要吃饭了啊---------

    弄懂之后我们再来新建个Impeat这样的类,同样是实现InterfaceDo接口

    public class Impgame implements InterfaceDo {
        private InterfaceDo todo;
        public Impgame(InterfaceDo todo) {
            super();
            this.todo = todo;
        }
        public void dosomething() {
            System.out.println("我要玩游戏了啊--------");
            todo.dosomething();
        }
    }

    上面接口实现类的含参构造函数的参数是InterfaceDo(接口)类型,所以参数可以是该接口所有实现类的实例化对象。

    4.多态的运用

    public class Testperson {
        public static void main(String[] args) {
            Persontodo a = new Persontodo();
            Impeat c = new Impeat(a);
            Impgame d = new Impgame(c);
            Impsleep b = new Impsleep(d);
            b.dosomething();
        }
    }

    我们可以看到这个测试类,将原始功能类的实例化对象作为参数传给Impeat的含参构造器,然后将Impeat的实例化对象

    作为参数传给Impgame的含参构造器,再将Impgame的实例化对象作为参数传给Impsleep的含参构造器,最后调用了

    Impgame的实例化对象的dosomething()方法。

    那么,实际上这个方法是:

    先调用参数的dosomething()方法然后打印一条语句,而参数的dosomething()方法也是

    先调用参数的dosomething()方法然后打印一条语句,如此循环,可以用一张图表示。

    -----------------------------------------------------------------------------

    -----------------------------------------------------------------------------

    每个框都是一个类,当然新增功能顺序可以自由选择,你也可以先实现功能2在实现1。

    如此一来每个除原始功能类之外的功能类,都是具备往其他功能类上添加功能的能力的。

    由于上面所有的类都是实现InterfaceDo接口的,那么可以将上面的代码改写一下:

    public class Testperson {
        public static void main(String[] args) {
            InterfaceDo a = new Persontodo();
            InterfaceDo c = new Impeat(a);
            InterfaceDo d = new Impgame(c);
            InterfaceDo b = new Impsleep(d);
            b.dosomething();
        }
    }

    不难看出,这就是引用多态,接口的引用指向实现类的对象。

    c在a的功能基础上添加了功能;

    d在c的功能基础上添加了功能;

    b在d的功能基础上添加了功能。

    这就实现了静态代理。

  • 相关阅读:
    【pytorch】torch.manual_seed()用法详解
    【python】具体能做些什么?(有哪些应用领域)
    【python】函数参数前加*星号的含义
    【python】Keyword-Only Arguments(强制关键字参数)
    【python】字符串find()方法
    碧蓝航线内部表情包(有爱自取)
    【python】60行代码实现给头像戴上圣诞帽(opencv)
    【python】30行代码实现视频中的动漫人脸检测(opencv)
    Linux supervisord配置使用 ubuntu
    BananaPi python-Mysql 操作库
  • 原文地址:https://www.cnblogs.com/eco-just/p/7853180.html
Copyright © 2011-2022 走看看