前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代理模式 Proxy Pattern

代理模式 Proxy Pattern

作者头像
FoamValue
发布2020-11-06 13:19:41
3320
发布2020-11-06 13:19:41
举报
文章被收录于专栏:FoamValueFoamValue

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

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


静态代理

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

一个简单的演示如下:

演示代码

代码语言:javascript
复制
// 简单接口类
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 提供了动态代理来解决这个问题。

改造演示

演示代码

代码语言:javascript
复制
// 动态代理类
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 。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FoamValue 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档