设计模式之代理模式--慕课网笔记

第1章 代理模式概念介绍
1-1 代理模式概念及分类
  • 面向对象的设计思维
  • 了解多态的概念
  • 了解反射机制

  • 代理模式基本概念及分类

  • 了解代理模式开发中应用场景
  • 掌握代理模式实现方法
  • 理解JDK动态代理实现

代理模式定义:为其他对象提供一种代理以控制这个对象的访问。
代理对象起到中介作用,可去掉功能服务或增加额外的服务。

  • 远程代理
    为不同地理的对象,提供局域网代表对象
  • 虚拟代理
    根据需要将资源消耗很大的对象进行延时,真正需要的时候进行创建
  • 保护代理
    控制对一个对象的访问的权限
  • 智能代理
    提供对目标对象额外服务
第2章 常用代理模式原理
2-1 静态代理概念及实现

智能引用代理

  • 静态代理
  • 动态代理

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

public interface Moveable {
    void move();
}
public class Car implements Moveable {

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

}
public class Car2 extends Car {

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        super.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }


}
public class Car3 implements Moveable {

    public Car3(Car car) {
        super();
        this.car = car;
    }

    private Car car;

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        car.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }

}
public class Client {

    /**
     * 测试类
     */
    public static void main(String[] args) {
//      Car car = new Car();
//      car.move();
        //使用集成方式
//      Moveable m = new Car2();
//      m.move();
        //使用聚合方式实现
        Car car = new Car();
        Moveable m = new Car3(car);
        m.move();
    }

}

通过继承和聚合两种方式都能实现代理,但究竟哪种更好呢?

2-2 聚合比继承更适合代理模式

实现功能叠加

  • 方法move()
  • 增加方法运行时间处理
  • 增加权限管理
  • 增加日志处理
public interface Moveable {
    void move();
}
public class Car implements Moveable {

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

}
public class CarLogProxy implements Moveable {

    public CarLogProxy(Moveable m) {
        super();
        this.m = m;
    }

    private Moveable m;

    @Override
    public void move() {
        System.out.println("日志开始....");
        m.move();
        System.out.println("日志结束....");
    }

}
public class CarTimeProxy implements Moveable {

    public CarTimeProxy(Moveable m) {
        super();
        this.m = m;
    }

    private Moveable m;

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        m.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }

}
public class Client {

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

}
2-3 了解 JDK 动态代理

动态产生代理,实现对不同类,不同方法的代理

ProxySubject->Proxy–>ProxyHandler–>RealSubject

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

  • Interface InvocationHandler:该接口中仅定义了一个方法public object invoke(
    Object obj,Method method,Object[] args)在实际使用时,第一个参数obj一般是指
    代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理中
    动态实现。
  • Proxy:该类即为动态代理类static Object newProxyInstance(ClassLoader loader,
    Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类
    可以当作被代理类使用(可使用被代理类的在接口中声明过的方法)
public interface Moveable {
    void move();
}
public class Car implements Moveable {

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

}
public class TimeHandler implements InvocationHandler {

    public TimeHandler(Object target) {
        super();
        this.target = target;
    }

    private Object target;

    /*
     * 参数:
     * proxy  被代理对象
     * method  被代理对象的方法
     * args 方法的参数
     * 
     * 返回值:
     * Object  方法的返回值
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        method.invoke(target);
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
        return null;
    }

}
public class Test {

    /**
     * JDK动态代理测试类
     */
    public static void main(String[] args) {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Class<?> cls = car.getClass();
        /**
         * loader  类加载器
         * interfaces  实现接口
         * h InvocationHandler
         */
        Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),
                                                cls.getInterfaces(), h);
        m.move();
    }

}

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

动态代理实现步骤

  • 创建一个实现接口InvocationHandler的类,它必须实现invoke方法
  • 创建被代理的类以及接口
  • 调用Proxy的静态方法,创建一个代理类
    newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
  • 通过代理调用方法
2-4 使用 cglib 动态产生代理
  • JDK动态代理
    • 只能代理实现了接口的类
    • 没有实现接口的类不能实现JDK的动态代理
  • CGLIB动态代理
    • 针对类来实现代理的
    • 对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用
public class Train {

    public void move(){
        System.out.println("火车行驶中...");
    }
}
public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz){
        //设置创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);

        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     * obj  目标类的实例
     * m   目标方法的反射对象
     * args  方法的参数
     * proxy代理类的实例
     */
    @Override
    public Object intercept(Object obj, Method m, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("日志开始...");
        //代理类调用父类的方法
        proxy.invokeSuper(obj, args);
        System.out.println("日志结束...");
        return null;
    }

}
public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {

        CglibProxy proxy = new CglibProxy();
        Train t = (Train)proxy.getProxy(Train.class);
        t.move();
    }

}
第3章 自定义类模拟 JDK 动态代理的实现
3-1 模拟 JDK 动态代理实现思路分析及简单实现

动态代理实现思路
实现功能:通过Proxy的newProxyInstance返回代理对象

  1. 声明一段源码(动态产生代理)
  2. 编译源码(JDK Compiler API),产生新的类(代理类)
  3. 将这个类load到内存当中,产生一个新的对象(代理对象)
  4. return 代理对象
3-2 完善动态代理实现
public interface Moveable {
    void move();
}
public class Proxy {

    public static Object newProxyInstance(Class infce) throws Exception{
        String rt = "\r\n";
        String methodStr = "";
        for(Method m : infce.getMethods()){
            methodStr += "  @Override" + rt +
            "   public void " + m.getName() + "() {" + rt +
            "       long starttime = System.currentTimeMillis();" + rt +
            "       System.out.println(\"汽车开始行驶....\");" + rt +
            "       m." + m.getName() + "();" + rt +
            "       long endtime = System.currentTimeMillis();" + rt +
            "       System.out.println(\"汽车结束行驶....  汽车行驶时间:\" " + rt +
            "               + (endtime - starttime) + \"毫秒!\");" + rt +
            "   }" ;
        }

        String str =
        "package com.imooc.proxy;" + rt +
        "public class $Proxy0 implements " + infce.getName() + " {" + rt +
        "   public $Proxy0(" + infce.getName() + " m) {" + rt +
        "       super();" + rt +
        "       this.m = m;" + rt +
        "   }" + rt +
        "   private " + infce.getName() + " m;" + rt +
        methodStr + rt +
        "}" ;
        //产生代理类的java文件
        String filename = System.getProperty("user.dir") +"/bin/com/imooc/proxy/$Proxy0.java";
        File file = new File(filename);
        FileUtils.writeStringToFile(file, str);

        //编译
        //拿到编译器
        JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
        //文件管理者
        StandardJavaFileManager fileMgr = 
                complier.getStandardFileManager(null, null, null);
        //获取文件
        Iterable units = fileMgr.getJavaFileObjects(filename);
        //编译任务
        CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);
        //进行编译
        t.call();
        fileMgr.close();

        //load 到内存
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class c = cl.loadClass("com.imooc.proxy.$Proxy0");

        Constructor ctr = c.getConstructor(infce);
        return ctr.newInstance(new Car());
    }




}
public class Client {

    /**
     * 测试类
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class);
        m.move();
    }

}
3-3 动态代理实现添加 InvocationHandler
public interface Moveable {
    void move();
}
public class Car implements Moveable {

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

}
public interface InvocationHandler {

    public void invoke(Object o,Method m);
}
public class TimeHandler implements InvocationHandler {

    private Object target;

    public TimeHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public void invoke(Object o, Method m) {

        try {
            long starttime = System.currentTimeMillis();
            System.out.println("汽车开始行驶....");
            m.invoke(target);
            long endtime = System.currentTimeMillis();
            System.out.println("汽车结束行驶....  汽车行驶时间:"
                            + (endtime - starttime) + "毫秒!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
public class Proxy {

    @SuppressWarnings("unchecked")
    public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{
        String rt = "\r\n";
        String methodStr = "";
        for(Method m : infce.getMethods()){
            methodStr += "  @Override" + rt +
            "   public void " + m.getName() + "() {" + rt +
            "  try{" + rt +
            "  Method md = " + infce.getName() + ".class.getMethod(\"" 
                                        + m.getName() + "\");" + rt +
            "  h.invoke(this,md);" +rt+ 
            "  }catch(Exception e){ e.printStackTrace();}" + rt +
            "   }" ;
        }

        String str =
        "package com.imooc.proxy;" + rt +
        "import java.lang.reflect.Method;" + rt +
        "import com.imooc.proxy.InvocationHandler;" +  rt+
        "public class $Proxy0 implements " + infce.getName() + " {" + rt +
        "   public $Proxy0(InvocationHandler h) {" + rt +
        "       this.h = h;" + rt +
        "   }" + rt +
        "  private InvocationHandler h;" + rt+ 
        methodStr + rt +
        "}" ;
        //产生代理类的java文件
        String filename = System.getProperty("user.dir") +"/bin/com/imooc/proxy/$Proxy0.java";
        File file = new File(filename);
        FileUtils.writeStringToFile(file, str);

        //编译
        //拿到编译器
        JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
        //文件管理者
        StandardJavaFileManager fileMgr = 
                complier.getStandardFileManager(null, null, null);
        //获取文件
        Iterable units = fileMgr.getJavaFileObjects(filename);
        //编译任务
        CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);
        //进行编译
        t.call();
        fileMgr.close();

        //load 到内存
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class c = cl.loadClass("com.imooc.proxy.$Proxy0");

        Constructor ctr = c.getConstructor(InvocationHandler.class);
        return ctr.newInstance(h);
    }




}
public class Client {

    /**
     * 测试类
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class,h);
        m.move();
    }

}
第4章 代理模式总结
4-1 课程总结
  • 代理概念、分类及应用场景
  • 静态代理(继承、聚合)
  • JDK动态代理实现日志处理功能
    • 产生动态代理不仅可以使用jdk动态代理,也可以使用其他的方式,如cglib.
  • 模拟JDK动态代理实现

常见代理模

  • 远程代理
  • 智能引用代理
  • 虚拟代理
  • 保护代理

智能引用代理

  • 日志处理
  • 权限管理
  • 事务处理

也叫AOP面向切面编程


《模式的秘密—代理模式》视频地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值