模式的秘密---代理模式

第1章 代理模式概念介绍

本章讲述了代理模式的分类、应用场景及作用

第2章 常用代理模式原理

本章介绍静态代理、动态代理实现原理。并通过案例讲解 JDK 动态代理以及使用 cglib 实现动态代理

引入包快捷键

打印快捷键

继承的方式实现静态代理:调用父类的方法。

使用聚合的方式,通过把参数传入进来,调用move方法。

 

 

更正:第一个参数一般是指被代理类。

 创建被代理的类以及接口:被代理的类Car,被代理的接口Moveable

cglib-nodep-2.2.2.jar 下载地址

http://www.java2s.com/Code/Jar/c/Downloadcglibnodep213jar.htm

package com.imooc.proxy;

public interface Moveable {
    void move();
}
 1 package com.imooc.proxy;
 2 
 3 import java.util.Random;
 4 
 5 public class Car implements Moveable {
 6 
 7     @Override
 8     public void move() {
 9         long starttime = System.currentTimeMillis();
10         System.out.println("汽车开始行驶...");
11         // 实现开车
12         try {
13             Thread.sleep(new Random().nextInt(1000));
14             System.out.println("汽车行驶中....");
15         } catch (InterruptedException e) {
16             e.printStackTrace();
17         }
18         long endtime = System.currentTimeMillis();
19         System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒!");
20     }
21 
22 }
package com.imooc.proxy;

public class Client {
    /**
     * 测试类
     */
    public static void main(String[] args) {
        Car car = new Car();
        car.move();
    }
}

静态代理的实现

使用继承的方式实现静态代理

package com.imooc.proxy;

public interface Moveable {
    void move();
}
 1 package com.imooc.proxy;
 2 
 3 import java.util.Random;
 4 
 5 public class Car implements Moveable {
 6     @Override
 7     public void move() {
 8         // 实现开车
 9         try {
10             Thread.sleep(new Random().nextInt(1000));
11             System.out.println("汽车行驶中....");
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15     }
16 
17 }
package com.imooc.proxy;

public class Car2 extends Car {
    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶...");
        super.move();//使用继承的方式实现Car2对Car的代理
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒!");
    }
}
package com.imooc.proxy;

public class Client {
    /**
     * 测试类
     */
    public static void main(String[] args) {
//        Car car = new Car();
//        car.move();
        
        Moveable m=new Car2();
        m.move();
    }
}

 使用聚合的方式实现静态代理

什么是聚合?

通过传进来的参数来调用move()方法

package com.imooc.proxy;

public interface Moveable {
    void move();
}
package com.imooc.proxy;

import java.util.Random;

public class Car implements Moveable {
    @Override
    public void move() {
        // 实现开车
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽车行驶中....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
 1 package com.imooc.proxy;
 2 
 3 public class Car3 implements Moveable {
 4     private Car car;
 5 
 6     public Car3(Car car) {
 7         super();
 8         this.car = car;
 9     }
10 
11     @Override
12     public void move() {
13         long starttime = System.currentTimeMillis();
14         System.out.println("汽车开始行驶...");
15         car.move();//使用聚合的方式实现Car3对Car的代理
16         long endtime = System.currentTimeMillis();
17         System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒!");
18 
19     }
20 
21 }
 1 package com.imooc.proxy;
 2 
 3 public class Client {
 4     /**
 5      * 测试类
 6      */
 7     public static void main(String[] args) {
 8 //        Car car = new Car();
 9 //        car.move();
10         //使用继承方式
11 //        Moveable m=new Car2();
12 //        m.move();
13         //使用聚合方式实现
14         Car car = new Car();
15         Moveable m=new Car3(car);
16         m.move();
17     }
18 }

 使用聚合的方式实现功能的叠加(对时间、日志的代理)

package com.imooc.proxy;

public interface Moveable {
    void move();
}
 1 package com.imooc.proxy;
 2 
 3 import java.util.Random;
 4 
 5 public class Car implements Moveable {
 6     @Override
 7     public void move() {
 8         // 实现开车
 9         try {
10             Thread.sleep(new Random().nextInt(1000));
11             System.out.println("汽车行驶中....");
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15     }
16 
17 }
 1 package com.imooc.proxy;
 2 //对时间的代理
 3 public class CarTimeProxy implements Moveable {
 4     private Moveable m;
 5 
 6     public CarTimeProxy(Moveable m) {
 7         super();
 8         this.m = m;
 9     }
10 
11     @Override
12     public void move() {
13         long starttime = System.currentTimeMillis();
14         System.out.println("汽车开始行驶...");
15         m.move();//使用聚合的方式实现Car3对Car的代理
16         long endtime = System.currentTimeMillis();
17         System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒!");
18 
19     }
20 
21 }
 1 package com.imooc.proxy;
 2 //对日志的代理
 3 public class CarLogProxy implements Moveable {
 4     private Moveable m;
 5 
 6     public CarLogProxy(Moveable m) {
 7         super();
 8         this.m = m;
 9     }
10 
11     @Override
12     public void move() {
13         System.out.println("日志开始...");
14         m.move();
15         System.out.println("日志结束..." );
16 
17     }
18 
19 }
 1 package com.imooc.proxy;
 2 //使用聚合的方式,代理之间可以互相传递的
 3 public class Client {
 4     /**
 5      * 测试类
 6      */
 7     public static void main(String[] args) {
 8         //创建子类对象,调用的方法为子类重写的方法或者继承的方法
 9         Car car=new Car();
10         
11         //先记录日志再记录时间
12 //        CarTimeProxy ctp = new CarTimeProxy(car);
13 //        CarLogProxy clp=new CarLogProxy(ctp);
14 //        clp.move();
15         
16         //先记录时间再记录日志
17         CarLogProxy clp=new CarLogProxy(car);
18         CarTimeProxy ctp = new CarTimeProxy(clp);
19         ctp.move();
20     }
21 }

动态代理实现

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

 1 package com.imooc.jdkproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class TimeHandler implements InvocationHandler {
 7 
 8     private Object target;
 9 
10     public TimeHandler(Object target) {
11         super();
12         this.target = target;
13     }
14 
15     /**
16      * 参数: 
17      * proxy 被代理对象
18      * method 被代理对象的方法 
19      * args 方法的参数
20      * 
21      * 返回值:
22      * Object 方法的返回值
23      */
24 
25     @Override
26     public Object invoke(Object proxy, Method method, Object[] args)
27             throws Throwable {
28         long starttime = System.currentTimeMillis();
29         System.out.println("汽车开始行驶...");
30         method.invoke(target);
31         long endtime = System.currentTimeMillis();
32         System.out.println("汽车结束行驶...汽车行驶时间:" + (endtime - starttime) + "毫秒!");
33         return null;
34     }
35 
36 }

2.创建被代理的类以及接口

package com.imooc.proxy;

public interface Moveable {
    void move();
}
 1 package com.imooc.proxy;
 2 
 3 import java.util.Random;
 4 
 5 public class Car implements Moveable {
 6     @Override
 7     public void move() {
 8         // 实现开车
 9         try {
10             Thread.sleep(new Random().nextInt(1000));
11             System.out.println("汽车行驶中....");
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15     }
16 
17 }

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

4.通过代理调用方法

 1 package com.imooc.jdkproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 import com.imooc.proxy.Car;
 8 import com.imooc.proxy.Moveable;
 9 
10 public class Test {
11 
12     /**
13      * JDK动态代理测试类
14      */
15     public static void main(String[] args) {
16         Car car = new Car();
17         InvocationHandler h = new TimeHandler(car);
18         Class<?> cls = car.getClass();
19         /**
20          * 动态创建代理类 
21          * loader 类加载器 
22          * interfaces 实现接口 
23          * h InvocationHandler 事务处理器
24          */
25         // Proxy.newProxyInstance(loader, interfaces, h)
26         // 对时间的动态代理
27         Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),
28                 cls.getInterfaces(), h);
29         m.move();//相当于method.invoke(Object proxy,Object[] args)
30                  //相当于move.invoke(m)
31     }
32 }

第3章 自定义类模拟 JDK 动态代理的实现

本章通过编写自定义类,模拟 JDK 动态代理的实现,帮助大家深入理解 JDK 动态代理的实现原理与机制

commons-io-2.6.jar下载地址

https://mvnrepository.com/artifact/commons-io/commons-io/2.6

抛出异常快捷键

ctrl+1

第4章 代理模式总结

总结代理模式分类、应用场景、实现原理、实现方式及实现方式优缺点

 

原文地址:https://www.cnblogs.com/songsongblue/p/9882066.html