代理模式


代理模式

代理模式的作用

我发现学习设计模式遇到的一个最大的困惑就是,自己搞不明白费那么大劲,增加那么多的编码
意义到底时什么。
所以在学习任何一种设计模式的时候,应该最先了解该设计模式到底解决了什么问题。
代理模式的作用是什么呢?

比如说我的同事走了,把手中的代码全部交接给我了,其中有个方法需要进行修改,
然后离开的同事代码写了一大坨没有任何中文注释,嵌套继承用了一大堆,别说改
了就是读明白都感觉困难。这时候怎么办呢?

这时候我们的代理模式就可以华丽登场了。我们可以在不改变源代码的情况下,对原来的
方法进行修改和增强,具体请看如下情况

静态代理

  • 接口
public interface ITeacherDao {
    void teach();
}
  • 被代理类
public class TeacherDao implements ITeacherDao{
    @Override
    public void teach() {
        System.out.println("被代理对象方法执行……");
    }
}
  • 代理类
public class TeacherDaoProxy implements ITeacherDao{

    private ITeacherDao target;

    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("执行一些方法……");
        target.teach();
        System.out.println("再执行一些方法……");
    }
}
  • 调用
public class Client {
    public static void main(String[] args) {
        TeacherDao teacherDao = new TeacherDao();
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
        teacherDaoProxy.teach();

    }
}
  • 执行结果
执行一些方法……
被代理对象方法执行……
再执行一些方法……
  • 优缺点

优点:在不改变被代理类代码的情况下,对被代理类的方法进行了增强。

缺点:因为代理和被代理类都要实现共同的接口,当接口发生改变时,接口的实现类都要改变。

动态代理

  • 接口
public interface ITeacherDao {
    void teach();
}
  • 被代理类
public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println("被代理对象方法执行……");
    }
}
  • 代理工厂
public class ProxyFactory {
    // 维护一个目标对象
    private Object target;

    // 构造器对target初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 给目标对象生成代理对象
    /*
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
  ClassLoader:指定当前目标对象使用的加载器,获取加载器的方法固定
  Class<?>[]:目标对象实现的接口类型,使用泛型的方式确认类型
  InvocationHandler:时间处理,执行目标对象的方法时,会执行处理器方法,会把当前执行的目标对象方法,作为一个参数传入
     */
    public Object getProxyInstance(){

        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("jdk 代理开始,执行其他方法……");
                // 反射机制调用目标对象的方法
                Object returnValue = method.invoke(target, args);
                System.out.println("jdk 代理结束,执行其他方法……");
                return returnValue;
            }
        });
    }
}
  • 调用
public class Client {
    public static void main(String[] args) {
        // 创建目标对象
        ITeacherDao target = (ITeacherDao) new TeacherDao();

        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

        // 内存中生成了代理对象
        System.out.println(proxyInstance);
        System.out.println(proxyInstance.getClass());

        proxyInstance.teach();
    }
}
  • 返回结果
jdk 代理开始,执行其他方法……
被代理对象方法执行……
jdk 代理结束,执行其他方法……
  • 优缺点

需要代理什么什么对象,直接在工厂取就可以,但是增强的方法不能随着被代理的对象的改变而改变

Cglib代理

  • 没有实现任何接口也可以被代理
  • 子类代理,在内存中实现被代理的子类,然后实现动态代理
  • 需要下载包,springAop的实现就用到了cglib包
  • 如果目标接口需要实现一个接口,就用jdk,如果目标对象不需要实现接口,则用cglib
  • 通过字节码生成新的类

出处

https://www.bilibili.com/video/BV1G4411c7N4?p=94

文章作者: 张一雄
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张一雄 !
  目录