• 代理设计模式


    案例需求:需要在原来的dao实现类的方法中,加入日志的记录功能,对原有的功能进行增强

    1. 静态代理

    静态代理的组成:

    抽象接口:目标类和代理类必须实现同一个抽象接口。

    目标类:封装了原始的核心功能

    代理类:拥有目标对象的引用,同时完成扩展功能的实现

    总结:将核心功能和扩展功能在代码的实现上,进行了分离在使用的时候将分离实现的功能进行合并。

    应用场景:对系统中原有的功能进行升级(可以不修改源码 )

    系统中如果分散着一些共性的,公共功能的代码(将这样功能的代码抽取进行单独的开发)

         

    2. 动态代理

    动态代理的实现原理:

    动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

    2.1动态代理实现的API

    Proxy 提供用于创建动态代理类和实例的静态方法

    static Object      newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

    返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序

    InvocationHandler 是代理实例的调用处理程序 实现的接口

    当使用代理类的对象调用某个方法的时候 ,该方法的执行会被InvocationHandler对象拦截

     Object     invoke(Object proxy, Method method, Object[] args) 

    在代理实例上处理方法调用并返回结果。

    2.2 创建Dao接口

    1 public interface Dao
    2 {
    3     public String save(String uname);
    4     public String delete(Integer id);
    5 }

    2.3 创建实现类

     1 public class DaoImpl implements Dao
     2 {
     3     @Override
     4     public String save(String uname)
     5     {
     6         /**
     7          * code....
     8          * **/
     9         System.out.println("----------数据保存到数据库---------");
    10         return "hello  " + uname;
    11     }
    12 
    13     @Override
    14     public String delete(Integer id)
    15     {
    16         // TODO Auto-generated method stub
    17         System.out.println("----------数据库删除操作------------");
    18         return "id=" + id;
    19     }
    20 }

    2.4创建工具类

    产生代理对象

     1 public class GetProxyInstance
     2 {
     3     private Object target; // 目标对象
     4 
     5     public GetProxyInstance()
     6     {
     7     }
     8 
     9     public GetProxyInstance(Object target)
    10     {
    11         this.target = target;
    12     }
    13 
    14     public Object getProxyInstance()
    15     {
    16         System.out.println("----------getProxyInstance");
    17         return Proxy.newProxyInstance(GetProxyInstance.class.getClassLoader(),// 类加载器对象
    18                 new Class[]
    19                 { Dao.class },// 代理对象需要实现的接口
    20                 new MyInvocationHandler());// 代理对象调用的方法对应的处理器
    21     }
    22 
    23     // 代理对象调用的方法对应的处理器类
    24     class MyInvocationHandler implements InvocationHandler
    25     {
    26         @Override
    27         public Object invoke(Object proxy, // 代理对象
    28                 Method method, // 被拦截到的方法
    29                 Object[] args) // 拦截的方法执行需要的参数
    30                 throws Throwable
    31         {
    32             // TODO Auto-generated method stub
    33             String methodName = method.getName();// 获得方法的名称
    34             // System.out.println(methodName+"--------"+Arrays.toString(args));
    35             if (methodName.equals("save"))
    36             {
    37                 System.out.println("-------完成日志的记录----------" + new Date()
    38                         + "----" + Arrays.toString(args));
    39             }
    40             // 通过反射完成方法的调用:完成目标对象方法的调用,放行
    41             Object rv = method.invoke(target, args);
    42             //
    43             return rv;
    44         }
    45     }
    46 }

    2.5 创建测试类

     1 public class TestProxy
     2 {
     3     public static void main(String[] args)
     4     {
     5         // 创建GetProxyInstance对象,传入被代理的目标对象
     6         GetProxyInstance gpi = new GetProxyInstance(new DaoImpl());
     7         // 获得代理对象
     8         Object obj = gpi.getProxyInstance();
     9         // System.out.println(obj instanceof Dao);
    10         // 向下转型
    11         Dao dao = (Dao) obj;
    12         String result = dao.save("乌龟");
    13         String result2 = dao.delete(100);
    14         // System.out.println("======"+result);
    15         System.out.println(dao.getClass());
    16         new DaoImpl().save("王八");
    17     }
    18 }

     

  • 相关阅读:
    三种钱是花的越多,赚的越多
    程序员除去繁华,你的匠心何在?
    科目三考试
    药房托管
    文章标题
    【cocos2d-x 3.7 飞机大战】 决战南海I (八) 背景移动
    Android开发时经经常使用的LogUtil
    仿支付宝/微信的password输入框效果GridPasswordView解析
    hdoj 1518 Square 【dfs】
    mysql配置文件夹错误:在安装mysql 5.6.19 时运行cmake命令是出现CMake Error: The source directory does not appear to contai
  • 原文地址:https://www.cnblogs.com/guanghe/p/6058371.html
Copyright © 2020-2023  润新知