zoukankan      html  css  js  c++  java
  • 代理模式:利用JDK原生动态实现AOP

    目录

    概述与模型

    1、概述

      含义:控制对对象的访问。

      作用:详细控制某个(某类)某对象的方法,在调用之前做前置处理,调用之后做后置处理,从而实现将统一流程代码放在代理类中处理。

      举例:我们在学习JDBC的时候,在批量处理的时候遇到过事务。流程:设置提交方式为手动提交-开启事务-批量处理-关闭事务-设置提交方式为默认。从这里我们清晰可以看见,每次进行批处理的时候,唯有增删改操作变化,其他的操作都是一样的。那么,我们可不可以把一样的操作提取出来交给一个类处理,批量操作提取出来交给一个类实现?带着疑问,我们来看一下代理模式的模型,你就有所明白了。

    2、模型

      

      Subject(抽象角色):定义代理角色和真实角色的公共对外方法。

      RealSubject(真实角色):实现抽象角色,定义真实角色所要实现的真实业务逻辑,供代理角色调用。

      Proxy(代理角色):实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

      最终目标:将统一的流程控制放到代理角色处理。

    应用场景描述

      1、安全代理:屏蔽对真实角色的直接访问,由代理角色控制,等业务真实需要的时候,才由代理对象调用真实对象方法。

      2、远程代理:通过代理类处理远程方法调用(RMI)。

      3、延迟代理:先加载轻量级的代理对象,真正需要再加载真实对象。例如加载图片、视频,先由代理对象在后台开启流对象,待真正需要浏览图片、视频的时候,才由真实对象加载图片,最后由代理对象关闭流对象。

      4、事务:解决概述举例内容,一层不变的内容由代理对象承担,而真正的业务逻辑由真实对象的方法实现。

      5、真实系统的日志处理、JDBC事务、Connection的开启与关闭。

      代码演示场景描述:假设一个明星被邀请去拍广告、拍电影,那么务必有这些流程:面谈->起草合同->安排机票、车票->出席活动->结算尾款。假设一年拍一两次广告,那么完全由一个明星自己解决。事实上,每个明星都有经纪人,而明星只专心负责出席活动,其他事务由经纪人操作。

      

    静态代理实现

    1、抽象角色

    2 public interface Star {
    3     //出席拍电影
    4     public void play();
    5     //出席拍广告
    6     public void advertise();
    7 }

    2、真实角色

     1 public class RealStar implements Star {
     2 
     3     public void play() {
     4         System.out.println("RealStar拍电影!");
     5     }
     6 
     7     public void advertise() {
     8         System.out.println("RealStar拍广告!");
     9     }
    10 
    11 }

    代理角色

    public class ProxyStar implements Star{
        Star star;
    
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ProxyStar(){}
    
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> ProxyStar(Star star) {
        </span><span style="color: #0000ff;">this</span>.star =<span style="color: #000000;"> star;
    }
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">面谈</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> interview() {
        System.out.println(</span>"ProxyStar interview"<span style="color: #000000;">);
    }
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">安排机票车辆</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> creatingContract() {
        System.out.println(</span>"ProxyStar creatingContract"<span style="color: #000000;">);
    }
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">出席演唱会</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> arrange() {
        System.out.println(</span>"ProxyStar arrange"<span style="color: #000000;">);
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> play() {
        System.out.println(</span>"#############"<span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">面谈</span>
    

    interview();
    //合同起草
    creatingContract();
    //安排机票车辆
    arrange();
    //出席演唱会
    star.play();
    //收尾款
    closeout();
    }

    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> advertise() {
        System.out.println(</span>"#############"<span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">面谈</span>
    

    interview();
    //合同起草
    creatingContract();
    //安排机票车辆
    arrange();
    //出席演唱会
    star.advertise();
    //收尾款
    closeout();
    }

    </span><span style="color: #008000;">//</span><span style="color: #008000;">收尾款</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> closeout() {
        System.out.println(</span>"ProxyStar closeout"<span style="color: #000000;">);
    }
    

    }

    4、客户端测试

     1 public class Client {
     2     public static void  main(String [] args){
     3         //真实明星王宝强
     4         Star realStar=new RealStar();
     5         //经纪人
     6         Star proxyStar=new ProxyStar(realStar);
     7         //邀约拍电影
     8         proxyStar.play();
     9         //邀约拍广告
    10         proxyStar.advertise();
    11     }
    12 }

    5、测试结果

      

    五、动态代理实现

    1、抽象角色、真实角色跟静态代理一致。

    2、StarHandler

     1 public class StarHandler implements InvocationHandler {
     2 
     3     Star star;
     4     public StarHandler(Star star){
     5         this.star=star;
     6     }
     7     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     8         Object object=null;
     9         System.out.println("###############");
    10         System.out.println("面谈!");
    11         System.out.println("起草合同。");
    12         System.out.println("安排机票。");
    13         if("play".equals(method.getName())||"advertise".equals(method.getName())){
    14             object=method.invoke(star,args);
    15         }
    16         System.out.println("收尾款。");
    17         return object;
    18     }
    19 }

    3、客户端调用

    public class Client {
        public static void  main(String [] args){
            //真实明星王宝强
            Star realStar=new RealStar();
           //动态处理类
            StarHandler handler=new StarHandler(realStar);
            //获得经纪人
            Star proxy= (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),realStar.getClass().getInterfaces(),handler);
    
        </span><span style="color: #008000;">//</span><span style="color: #008000;">出席拍电影</span>
    

    proxy.play();
    //出席拍广告
    proxy.advertise();
    }
    }

    4、测试结果

    结合注解模拟AOP

    1、抽象角色

    public interface Star {
        //出席拍电影
        @DoOddJob("play")
        public void play();
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">出席拍广告</span>
    @DoOddJob("advertise"<span style="color: #000000;">)
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> advertise();
    

    }

    2、真实角色

     1 public class RealStar implements Star {
     2 
     3     public void play() {
     4         System.out.println("RealStar拍电影!");
     5     }
     6 
     7     public void advertise() {
     8         System.out.println("RealStar拍广告!");
     9     }
    10 
    11 }

    3、StarHandler

    public class StarHandler implements InvocationHandler {
        //目标对象:真正的对象
        Object targetObject;
        InvocationHandler handler;
        public StarHandler(Object object){
            this.targetObject=object;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object object=null;
    
        System.out.println(</span>"###############"<span style="color: #000000;">);
        DoOddJob annotation</span>=method.getAnnotation(DoOddJob.<span style="color: #0000ff;">class</span><span style="color: #000000;">);
        System.out.println(annotation);
        System.out.println(</span>"面谈!"<span style="color: #000000;">);
        System.out.println(</span>"起草合同。"<span style="color: #000000;">);
        System.out.println(</span>"安排机票。"<span style="color: #000000;">);
        </span><span style="color: #0000ff;">if</span><span style="color: #000000;">(annotation.value().equals(method.getName())){
            object</span>=<span style="color: #000000;">method.invoke(targetObject,args);
        }
        System.out.println(</span>"收尾款。"<span style="color: #000000;">);
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> object;
    }
    
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object createProxy(){
        </span><span style="color: #0000ff;">return</span> Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),targetObject.getClass().getInterfaces(),<span style="color: #0000ff;">this</span><span style="color: #000000;">);
    }
    

    }

    4、自定义注解

    1 @Target({ElementType.METHOD,ElementType.TYPE})
    2 @Retention(RetentionPolicy.RUNTIME)
    3 public @interface DoOddJob {
    4     String value() default "";
    5 }

    5、客户端调用

     1 public class Client {
     2     public static void  main(String [] args){
     3         //真实明星王宝强
     4         Star realStar=new RealStar();
     5        //动态处理类
     6         StarHandler handler=new StarHandler(realStar);
     7         //获得经纪人
     8         Star proxy= (Star) handler.createProxy();
     9 
    10         //出席拍电影
    11         proxy.play();
    12         //出席拍广告
    13         proxy.advertise();
    14     }
    15 }

    6、测试结果

    回顾 

    1、代理模式是什么?代理模式有什么用?

      为了统一的流程控制,剔除重复的操作交由代理角色,真实角色负责真正的业务操作。

    2、静态代理与动态代理的区别?

      动态代理相对于静态代理,变得更加灵活,同时利用Java的动态性(反射、字节码操作、动态编译)处理更加容易。

      优点:抽象角色中(接口)生命的所有方法都被转移到调用处理器一个集中的方法处理,这样处理起来解耦,便于扩展,更加灵活。

    3、进一步思考

      AOP核心就是在真正业务前后添加一些统一流程(由代理对象实现)。同时,利用反射或者注解,便于获取参数,从而更加灵活。甚至,我们还可以做一个Handler工厂用于创建代理对象,使得我们运用更加方便。现在回想一下上面的应用场景,你是否有思路了呢?如果有思路了,不妨自己动手试试,加深对代理模式的理解,以便能更加深入理解后续知识。

  • 相关阅读:
    关于MySQL 最后一部安装阶段无法响应的问题
    为PHP 启用Mysql 的dll
    webcast终于改版了
    有意思的oracle转义字符
    Telnet协议详解及使用C# 用Socket 编程来实现Telnet协议
    我被百度悲剧了
    阻止 http://3b3.org/c.js恶意SQL注入
    驱动研究日记-链表+后备链表
    C# 执行汇编类
    Tuning and Slimming JBossAS
  • 原文地址:https://www.cnblogs.com/qiuyong/p/6412870.html
Copyright © 2011-2022 走看看