博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之代理模式
阅读量:6656 次
发布时间:2019-06-25

本文共 3293 字,大约阅读时间需要 10 分钟。

概念

  • 代理模式即:提供一个代理类来控制对目标对象的访问
  • 代理模式分为静态代理和动态代理,动态代理又有JDK动态代理和CGLIB动态代理。

静态代理

  • 静态代理指代理类在程序运行前就存在,代理类和目标类的关系也已经确定
  • 代理类和目标类需要实现同一个接口

优点

  • 可以在不修改目标对象的情况下,扩展目标对象的功能(符合对修改封闭,对扩展开放的原则)

缺点

  • 代码维护复杂度增加:代理类和目标类实现同一接口,接口增加方法的话目标类和代理类都需要修改。
  • 代码冗余度高:代理类只能代理一种类型的目标类

实例

  • 接口
public interface Workable {    /**     * 工作     */    void work();}复制代码
  • 目标对象
public class Star implements Workable{        @Override    public void work() {        System.out.println("明星演戏。");    }}复制代码
  • 代理对象
public class Agent implements Workable{    private Workable workable;        public Agent(Workable workable){        this.workable = workable;    }        @Override    public void work() {        System.out.println("经纪人帮明星谈片酬然后让他去演戏");        workable.work();        System.out.println("经纪人帮明星收钱");    }}复制代码
  • 测试类
public class Director {    public static void main(String... arg){        Workable star = new Star();        Workable agent = new Agent(star);        agent.work();    }}结果:经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱演戏的话需要找经纪人,经纪人控制对明星的访问(是不是接你的戏)明星只需要演戏就可以,剩下其他不想做的事都可以交给经纪人复制代码

动态代理

  • 代理类是程序运行时动态生成的
  • 实现AOP的基础

JDK动态代理

  • 又称接口代理,要求目标类必须实现接口
  • 主要涉及Proxy和InvocationHandler两个类 通过实现InvocationHandler接口定义横切逻辑,并通过反射调用目标类的代码。将横切逻辑和业务逻辑编织在一起。
  • 代理对象的所有接口方法调用都会转发到InvocationHandler.invoke()方法
实例
  • 横切逻辑
public class AgentHandler implements InvocationHandler {    private Workable workable;        public AgentHandler(Workable workable){        this.workable = workable;    }        // 将横切逻辑和业务代码编织在一起    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("经纪人帮明星谈片酬然后让他去演戏");        Object object = method.invoke(workable, args);        System.out.println("经纪人帮明星收钱");        return object;    }}复制代码
  • 测试
public class Director {    public static void main(String... arg){        Workable star = new Star();        // 创建代理类对象        Workable proxyInstance = (Workable)Proxy.newProxyInstance(star.getClass().getClassLoader(),                star.getClass().getInterfaces(), new AgentHandler(star));        proxyInstance.work();    }}结果:和静态代理一样经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱复制代码

动态代理可以代理多种类型的对象。

CGLib 动态代理

  • CGLib 采用底层的字节码技术,可以为一个类创建子类,在子类中通过方法拦截的方式拦截所有父类方法的调用,并织入横切逻辑。
  • 通过创建目标类的子类的方式
  • 涉及的类Enhancer 和 MethodInterceptor
实例
  • 横切逻辑
public class AgentInterceptor implements MethodInterceptor {    private Enhancer enhancer = new Enhancer();        /**     *  设置目标类来创建子类实例     * @param clazz 目标类     * @return obj     */    public Object getProxy(Class clazz){        enhancer.setSuperclass(clazz);        enhancer.setCallback(this);        return enhancer.create();    }        @Override    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        System.out.println("经纪人帮明星谈片酬然后让他去演戏");        // 通过代理类调用父类的方法        Object result = methodProxy.invokeSuper(object, args);        System.out.println("经纪人帮明星收钱");            return result;    }}复制代码
  • 测试
public class Director {    public static void main(String... arg){        AgentInterceptor agentInterceptor = new AgentInterceptor();        // 创建代理类对象        Star star = (Star) agentInterceptor.getProxy(Star.class);        star.work();    }}结果:和静态代理一样经纪人帮明星谈片酬然后让他去演戏明星演戏。经纪人帮明星收钱复制代码

通过生成目标类的子类,并实现MethodInterceptor接口的方法,拦截所有目标类的调用。

转载于:https://juejin.im/post/5d02629f6fb9a07ee742da97

你可能感兴趣的文章
深入浅出KnockoutJS
查看>>
浅谈Android样式开发之View Animation (视图动画)
查看>>
JavaScript eval()函数
查看>>
两点计算角度
查看>>
PN-Net: Conjoined Triple Deep Network for Learning Local Image Descriptors-论文解读
查看>>
【leetcode】38. Count and Say
查看>>
自己制作redis 和mongo 镜像
查看>>
正则表达式
查看>>
java Annotation注解
查看>>
CAPI学习心得
查看>>
数据结构与算法刷题
查看>>
MFC界面的完善
查看>>
【洛谷 P1651】 塔 (差值DP)
查看>>
考虑碰撞的二能级原子和电磁场的相互作用
查看>>
从乔布斯在斯坦福大学毕业典礼上的演讲感触
查看>>
无限级分类
查看>>
美化fedora字体
查看>>
【LeetCode】6 - ZigZag Conversion
查看>>
Ambiguous HTTP method Actions require an explicit HttpMethod binding for Swagger 2.0
查看>>
OpenSSL修复加密漏洞、加强Logjam防御
查看>>