zoukankan      html  css  js  c++  java
  • Java基础知识之设计模式--代理模式

    Java设计模式--代理模式

    声明:本文根据慕课网David老师的精品课程整理来的:慕课网

    什么是设计模式(Design Pattern)?

      设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。

    代理模式的定义?

      代理模式就是为其他对象提供一种代理,以控制对这个对象的访问。

      代理对象起到中介作用,可去掉功能服务或增加额外的服务。

    代理对象和目标对象的关系?

      代理对象:增强后的对象

      目标对象:被增强的对象

      他们不是绝对的,会根据情况发生变化。

    代理模式的两种实现方式?

      1.静态代理代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类。

      2.动态代理:JDK通过接口反射得到字节码,然后把字节码转换成class(通过native方法)

    静态代理实现的两种方式?

      使用继承方式实现和使用聚合方式实现。

      继承:代理对象继承目标对象,重写需要增强的方法。缺点:代理类过多,产生类爆炸。

      聚合:目标对象和代理对象实现同一个接口,代理对象当中要包含目标对象。

    动态代理的实现方式?

      Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

        1.Interface InvocationHandler : 该接口中仅定义了一个方法,public Object invoke(Object obj,Method method,Object[] args),在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args是该方法的参数数组,这个抽象方法在代理类中动态实现。

        2.Proxy 该类即为动态代理类,static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可使用被代理类在接口中声明过的方法)

        所谓的动态代理是这样一种class:它是在运行时生成的class,该class需要实现一组interface,使用动态代理类时,必须实现InvocationHandler接口。

    JDK动态代理和CGLIB动态代理的区别?

      1.JDK动态代理只能代理实现了接口的类,没有实现接口的类不能实现JDK的动态代理。

      2.CGLIB动态代理针对类来实现代理的,对指定目标类产生一个子类,通过方法拦截技术拦截所有的父类方法的调用。

    动态代理实现的思路:

      1.声明一段源码(动态产生代理)

      2.编译源码(JDK Compiler API ),产生新的类(代理类)

      3.将这个类load到内存中,产生一个新的对象(代理对象)

      4.return 代理对象。

    使用静态代理的例子:

      1.首先创建业务逻辑接口

     1 /**
     2  * 接口
     3  * @author Administrator
     4  *
     5  */
     6 public interface Moveable {
     7     /**
     8      * 
     9      * 接口中的方法
    10      * @Description: TODO
    11      * @returnType: void
    12      */
    13     void move();
    14 }
    View Code

      2.创建实现类,实现接口中的方法

     1 /**
     2  * 实现类
     3  * @author Administrator
     4  *
     5  */
     6 public class Car implements Moveable {
     7 
     8     @Override
     9     public void move() {
    10         //实现开车
    11         try {
    12             Thread.sleep(new Random().nextInt(1000));
    13             System.out.println("汽车行驶中...");
    14         } catch (InterruptedException e) {
    15             e.printStackTrace();
    16         }
    17     }
    18 
    19 }
    View Code

      3.使用继承方式实现对实现类的代理

     1 /**
     2  * 使用继承方式实现代理
     3  * @author Administrator
     4  *
     5  */
     6 public class Car2 extends Car {
     7 
     8     /* (non-Javadoc)
     9      * @see com.wk.design.proxy.Car#move()
    10      * 直接调用父类的move方法,这样就形成了一个Car2对Car的代理
    11      */
    12     @Override
    13     public void move() {
    14         long startTime = System.currentTimeMillis();
    15         System.out.println("汽车开始行驶...");
    16         //使用继承的方式调用父类的move()方法
    17         super.move();
    18         long endTime = System.currentTimeMillis();
    19         System.out.println("汽车行驶结束... 汽车行驶时间:"+(endTime-startTime)+"毫秒。");
    20     }
    21 
    22 }
    View Code

      4.创建测试类

     1 /**
     2  * 测试类
     3  * @author Administrator
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9 //        Car car = new Car();
    10 //        car.move();
    11         
    12         //使用继承方式实现代理
    13         Moveable car2 = new Car2();
    14         car2.move();
    15         
    16         //使用聚合方式实现代理
    17 //        Car car = new Car();
    18 //        Moveable car3 = new Car3(car);
    19 //        car3.move();
    20         
    21     }
    22 }
    View Code

      5.使用聚合方式实现对实现类的代理

        日志代理类

     1 /**
     2  * 
     3  * 日志代理类
     4  * @author Administrator
     5  *
     6  */
     7 public class CarLogProxy implements Moveable {
     8 
     9     /**
    10      * 使用接口声明代理类
    11      */
    12     private Moveable m;
    13     /**
    14      * 通过构造方法的参数传入代理类
    15      * @param m
    16      */
    17     public CarLogProxy(Moveable m) {
    18         super();
    19         this.m = m;
    20     }
    21 
    22     @Override
    23     public void move() {
    24         System.out.println("日志开始");
    25         //调用代理类的方法
    26         m.move();
    27         System.out.println("日志结束");
    28 
    29     }
    30 
    31 }
    View Code

        时间代理类

     1 /**
     2  * 时间代理类
     3  * @author Administrator
     4  *
     5  */
     6 public class CarTimeProxy implements Moveable {
     7 
     8     /**
     9      * 使用接口声明代理类
    10      */
    11     private Moveable m;
    12     /**
    13      * 通过构造方法的参数传入代理类
    14      * @param m
    15      */
    16     public CarTimeProxy(Moveable m) {
    17         super();
    18         this.m = m;
    19     }
    20 
    21     @Override
    22     public void move() {
    23         long startTime = System.currentTimeMillis();
    24         System.out.println("汽车开始行驶...");
    25         //调用代理类的方法
    26         m.move();
    27         long endTime = System.currentTimeMillis();
    28         System.out.println("汽车行驶结束... 汽车行驶时间:"+(endTime-startTime)+"毫秒。");
    29     }
    30 
    31 }
    View Code

      6.创建聚合方式测试类

     1 /**
     2  * 聚合代理测试类
     3  * @author Administrator
     4  *
     5  */
     6 public class TestJuHeProxy {
     7     public static void main(String[] args) {
     8         Car car = new Car();
     9         //先记录日志,再记录时间
    10 //        CarTimeProxy ctp = new CarTimeProxy(car);
    11 //        CarLogProxy clp = new CarLogProxy(ctp);
    12 //        clp.move();
    13         
    14         //先记录时间,再记录日志
    15         CarLogProxy clp = new CarLogProxy(car);
    16         CarTimeProxy ctp = new CarTimeProxy(clp);
    17         ctp.move();
    18     }
    19     
    20 }
    View Code

    使用JDK动态代理实现的例子:

      1.创建一个实现接口InvocationHandler的类,它必须实现invoke()方法。

      2.创建被代理类及接口

      3.调用Proxy的静态方法,创建一个代理类

      4.通过代理调用方法

     1 /**
     2  * 使用jdk的动态代理
     3  * @author Administrator
     4  *
     5  */
     6 public class TimeHandler implements InvocationHandler {
     7 
     8     /**
     9      * 被代理对象
    10      */
    11     private Object target;
    12     
    13     public TimeHandler(Object target) {
    14         super();
    15         this.target = target;
    16     }
    17 
    18     /**
    19      * 参数:
    20      * proxy : 被代理对象
    21      * method : 被代理对象的方法
    22      * args : 方法的参数
    23      * 返回值:
    24      * Object 方法的返回值
    25      */
    26     @Override
    27     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    28         //在执行被代理对象的方法之前执行自己的逻辑
    29         long startTime = System.currentTimeMillis();
    30         System.out.println("汽车开始行驶...");
    31         //执行被代理对象的方法
    32         method.invoke(target);
    33         //在执行被代理对象的方法之后执行自己的逻辑
    34         long endTime = System.currentTimeMillis();
    35         System.out.println("汽车行驶结束... 汽车行驶时间:"+(endTime-startTime)+"毫秒。");
    36         return null;
    37     }
    38 
    39 }
    View Code
     1 /**
     2  * JDK动态代理测试类
     3  * @author Administrator
     4  *
     5  */
     6 public class JdkProxyTest {
     7 
     8     public static void main(String[] args) {
     9         Car car = new Car();
    10         InvocationHandler h = new TimeHandler(car);
    11         Class<?> cls = car.getClass();
    12         /**
    13          * 参数:
    14          *     loader : 类加载器
    15          *  interfaces : 实现接口
    16          *  h InvocationHandler
    17          */
    18         Moveable m= (Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
    19         //执行被代理类的方法
    20         m.move();
    21     }
    22 
    23 }
    JDk动态代理测试类

    使用CGLIB动态代理实现的例子:

      1.创建代理类,实现MethodInterceptor接口

      2.使用Enhancer类创建代理方法

      3.创建被代理类,并编写代理方法

      4.通过代理调用方法

     1 /**
     2  * 使用cglib动态代理
     3  * @author Administrator
     4  *
     5  */
     6 public class Train {
     7     public void move(){
     8         System.out.println("火车行驶中。。。");
     9     }
    10 }
    View Code
     1 public class CglibProxy implements MethodInterceptor {
     2 
     3     private Enhancer enhancer = new Enhancer();
     4     //创建代理类方法
     5     public Object getProxy(Class clazz){
     6         //设置创建子类的类
     7         enhancer.setSuperclass(clazz);
     8         //回调函数
     9         enhancer.setCallback(this);
    10         //创建并返回子类的实例
    11         return enhancer.create();
    12     }
    13     /**
    14      * 作用:拦截所有目标类方法的调用
    15      * obj : 目标类的实例
    16      * m : 目标方法的反射对象
    17      * args : 方法的参数
    18      * proxy : 代理类的实例
    19      */
    20     @Override
    21     public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
    22         //在调用方法时实现自己的业务逻辑
    23         System.out.println("日志开始...");
    24         //代理类调用父类的方法
    25         proxy.invokeSuper(obj, args);
    26         //调用方法之后实现自己的业务逻辑
    27         System.out.println("日志结束...");
    28         return null;
    29     }
    30 }
    View Code
     1 /**
     2  * 使用cglib动态代理的测试类
     3  * @author Administrator
     4  *
     5  */
     6 public class CglibProxyTest {
     7 
     8     public static void main(String[] args) {
     9         CglibProxy proxy = new CglibProxy();
    10         //传入要代理的类
    11         Train t = (Train)proxy.getProxy(Train.class);
    12         //执行方法
    13         t.move();
    14     }
    15 
    16 }
    CGLIB动态代理测试类
  • 相关阅读:
    django 重建一个表
    近期数据工作的知识点总结(model-dict高级用法)
    搬运django中文网 CentOS7下部署Django项目详细操作步骤(django安装网站有时候打不开,备份用)
    创建ftp免密只读用户(外系统读取csv共享数据)
    某某系统从外部基础库读取数据
    离线安装 django-axes
    django queryset用法总结二
    django queryset用法总结一
    nginx 启动,停止 重启
    安装安全狗失败 ,linux wget的时候不去找目标ip,而是路由到其他ip,原因分析
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/12355396.html
Copyright © 2011-2022 走看看