专栏首页FoamValue代理模式 Proxy Pattern

代理模式 Proxy Pattern

Proxy Pattern,是 Java 常用的设计模式之一。它的定义是对其他对象提供一种代理,已达到控制对这个对象访问的目的。

本文主要介绍代理模式的两种实现方式:静态代理、动态代理。希望通过两种实现方式来加深对代理模式的理解。


静态代理

每个静态代理都需要三个类:接口类、实现类、代理实现类。其中每个静态代理实现都需要创建相对应的代理实现类,代理实现类通过聚合来实现静态代理。

一个简单的演示如下:

演示代码

// 简单接口类
public interface IUserDao {
    void say(); // 接口方法
}
// 接口实现类
public class UserDao implements  IUserDao {
    @Override
    public void say() {
        System.out.println("Hi, enjoy 1024.");
    }
}
// 静态代理 XxxProxy
public class UserDaoProxy implements IUserDao {
    private IUserDao target;
    public UserDaoProxy(IUserDao target) {
        this.target = target;
    }
    @Override
    public void say() {
        // say()执行前处理
        System.out.println("Proxy Begin");
        target.say();
        // say()执行后处理
        System.out.println("Proxy End");
    }
}
// 测试类
public class UserDaoTest {
    @org.junit.Test
    public void say() {
        UserDao userDao = new UserDao();
        UserDaoProxy proxy = new UserDaoProxy(userDao);
        proxy.say();
    }
}

运行结果


动态代理

针对静态代理出现的大量 XxxxProxy 代理实现类问题,JDK 提供了动态代理来解决这个问题。

改造演示

演示代码

// 动态代理类
public class ProxyHandler implements InvocationHandler {
    private Object target;
    public ProxyHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy Begin");
        method.invoke(target);
        System.out.println("Proxy End");
        return null;
    }
}
// 测试类
public class UserDaoTest {
    @org.junit.Test
    public void say02() {
        UserDao userDao = new UserDao();
        InvocationHandler handler = new ProxyHandler(userDao);
        Class<?> cls = userDao.getClass();
        /**
         * loader 类加载器
         * interfaces 实现接口
         * handler InvocationHandler
         * */
        IUserDao iUserDao = (IUserDao) Proxy.newProxyInstance(cls.getClassLoader(),
                cls.getInterfaces(), handler);
        iUserDao.say();
    }
}
// 简单接口2
public interface IPhoneDao {
    void buy();
}
// 简单接口实现2
public class PhoneDao implements IPhoneDao {
    @Override
    public void buy() {
        System.out.println("Buy IPhone 12 Pro Max!!!");
        System.out.println("No");
        System.out.println("Buy IPhone Xr ?");
        System.out.println("OK, It's good.");
    }
}
// 测试类
public class PhoneDaoTest {
    @org.junit.Test
    public void Buy() {
        PhoneDao phoneDao = new PhoneDao();
        InvocationHandler handler = new ProxyHandler(phoneDao);
        Class<?> cls = phoneDao.getClass();
        /**
         * loader 类加载器
         * interfaces 实现接口
         * handler InvocationHandler
         * */
        IPhoneDao iPhoneDao = (IPhoneDao) Proxy.newProxyInstance(cls.getClassLoader(),
                cls.getInterfaces(), handler);
        iPhoneDao.buy();
    }
}

运行结果


CGLib & Javassist

Byte Code Generation Library is high level API to generate and transform JAVA byte code. Javassist (Java Programming Assistant) makes Java bytecode manipulation simple.

除了JDK提供的静态代理、动态代理之外,还有另外两款优秀的开源库 CGLib、Javassist。


总结

JDK 自带的动态代理基本适用于常规的场景,熟练掌握可以灵活面对 80% 的情况。而剩下需要在运行时修改、创建类来实现动态代理的场景,就需要使用到 CGLib、Javassist 。

本文分享自微信公众号 - FoamValue(gh_3c635269f459),作者:陈鑫杰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 结构型构建模式

    适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式,它们是关注类和对象的组合为目的的设计模式,它们也被称为结构型构建模式。

    FoamValue
  • Servlet API 源码剖析

    从目录出发,整个源代码分为 servlet、http、descriptor、annotation 四个部分。

    FoamValue
  • 「拥抱开源」Nacos 实战篇

    启动之后,使用浏览器打开 http://localhost:8848/nacos。

    FoamValue
  • 静态代理和动态代理简介

    在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标对象之间起到中介的作用,并且...

    SmileNicky
  • 设计模式之代理模式(结构型)

    代理模式:代理模式就是引入一个代理对象,通过代理对象实现对原对象的引用。代理模式是一种对象结构型。

    SmileNicky
  • 设计模式-代理模式

    日常生活中,有非常多的代办、代处理,比如代找货源、代租房、代记、代办证件等,代办人就是这个代理的对象,通过代理人来达到办理的目的或结果,并且得到一样的结果。就比...

    逍遥壮士
  • 设计模式——代理模式

    现在有个非常流行的程序叫做面向切面编程(AOP),其核心就是采用了动态代理的方式。怎么用?Java为我们提供了一个便捷的动态代理接口 InvocationHan...

    蜻蜓队长
  • Java代理和动态代理机制分析和应用

    本博文中项目代码已开源下载地址:GitHub Java代理和动态代理机制分析和应用 概述 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个...

    CrazyCodeBoy
  • 打造一款 刷Java 知识的小程序(二)

    痛点:Markdown转小程序页面很难受,小程序页面并不能识别Markdown标记。

    悟空聊架构
  • GitHubPopular运行记录

    首先是gradle被墙解决 工作目录\GitHubPopular-master\android\gradle\wrapper\gradle-wrapper.p...

    易墨

扫码关注云+社区

领取腾讯云代金券