设计模式 - 代理模式

代理模式

代理模式是一种结构型设计模式,它允许你提供一个代理对象来控制对另一个对象的访问。代理模式可以在不改变原始对象的情况下,增强或控制对原始对象的访问。代理模式通常用于延迟加载、访问控制、日志记录、性能监控等场景。

1.静态代理

静态代理是指在编译时就已经确定代理类和被代理类的关系。静态代理通常需要手动编写代理类,并且代理类和被代理类实现相同的接口或继承相同的父类

java 复制代码
public interface OrderService {
    void save();
}

public class ProxyOrderService implements OrderService {

    // 被代理的对象
    private OrderService orderService;

    public ProxyOrderService(OrderService orderService) {
        this.orderService = orderService;
    }

    // 执行
    public static void main(String[] args) {
        // 创建被代理对象
        OrderService orderService = new OrderServiceImpl();

        // 创建代理对象
        ProxyOrderService proxy = new ProxyOrderService(orderService);

        proxy.save();
    }

    @Override
    public void save() {
        System.out.println("代理前置处理 ...");
        // 执行被代理的对象的方法
        orderService.save();
        System.out.println("代理后置处理 ...");
    }
}

2 动态代理

动态代理是指在运行时动态生成代理类,而不是在编译时手动编写代理类。

2.1 JDK动态代理

JDK动态代理基于Java反射机制实现,它需要被代理对象实现一个接口。

java 复制代码
/**
 * 代理对象 实现 InvocationHandler
 * InvocationHandler 该类做方法拦截所用, 通过此类可以对目标方法进行增强
 */
public class JDKProxyDynamic implements InvocationHandler, Serializable {

    private static final long serialVersionUID = 4431939583048226878L;
    private Object target;

    private Class<?> clazz;

    public JDKProxyDynamic(Class<?> clazz) {
        this.clazz = clazz;
    }

    /**
     * 通过该方法的调用对目标对象进行增强
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调度真实对象之前,方法名: " + method.getName() + ",参数:" + args);

        // Spring框架中使用动态代理,可以从applicationContext里面获取对应的target对象
        if (Objects.isNull(target)) {
            target = clazz.newInstance();
        }
        System.out.println("代理前置处理 ...");
        Object returnResult = method.invoke(target, args);
        System.out.println("代理后置处理 ...");
        return returnResult;
    }

    public static void main(String[] args) {
        // 创建动态代理对象,JDK动态代理只能代理实现接口的类
        OrderService proxyInstance = (OrderService) Proxy.newProxyInstance(
                OrderServiceImpl.class.getClassLoader(),
                OrderServiceImpl.class.getInterfaces(),
                new JDKProxyDynamic(OrderServiceImpl.class)
        );

        // 通过代理对象调用方法
        proxyInstance.save();
    }
}
2.2 CGLIB动态代理

CGLIB动态代理基于ASM字节码生成框架实现,它不需要被代理对象实现接口。CGLIB动态代理是针对类进行代理的,它通过继承目标类创建子类,并重写目标类的方法。

java 复制代码
public class CglibProxy implements MethodInterceptor {
    private static CglibProxy INSTANCE = new CglibProxy();

    private Object target;

    private Class<?> clazz;


    private CglibProxy() {
    }

    public CglibProxy(Class<?> clazz) {
        this.clazz = clazz;
    }

    public static CglibProxy getInstance() {
        return INSTANCE;
    }

    public Object getCglibProxyObject(Object target) {
        // 可以在Spring中获取指定对象,为其创建代理对象,再指定对应的target
        this.clazz = target.getClass();
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * @param object 被代理的对象
     * @param method 被代理对象需要执行的方法
     * @param args   被代理对象需要执行的方法 参数
     * @param proxy  触发父类的方法对象
     * @return 被代理对象需要执行的方法 返回值
     * @throws Throwable 抛出的异常信息
     */
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method execution: " + method.getName());
        Object result = proxy.invokeSuper(object, args);
        System.out.println("After method execution: " + method.getName());
        return result;
    }

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(OrderServiceImpl.class);
        enhancer.setCallback(new CglibProxy());
        OrderService orderService = (OrderService) enhancer.create();
        orderService.save();
    }
}
相关推荐
贵慜_Derek12 小时前
《从零实现 Agent 系统》连载 03|控制循环:感知—决策—行动—反思
人工智能·设计模式·架构
nnsix12 小时前
设计模式 - 原型模式 笔记
笔记·设计模式·原型模式
nnsix13 小时前
设计模式 - 适配器模式 笔记
笔记·设计模式·适配器模式
asdfg125896313 小时前
一文理解软件开发中的“设计模式”
java·设计模式·软件开发
云飞云共享云桌面14 小时前
SolidWorks 服务器通过云飞云共享云桌面10人研发共享方案
运维·服务器·3d·设计模式·电脑
蜡笔小马14 小时前
12.C++设计模式-模板方法模式
c++·设计模式·模板方法模式
雪度娃娃14 小时前
行为型设计模式——备忘录模式
服务器·c++·设计模式·备忘录模式
皮卡祺q14 小时前
【抽奖系统-0】Redis 缓存与 RabbitMQ 削峰实战;架构梳理
设计模式
蜡笔小马14 小时前
13.C++设计模式-策略模式
c++·设计模式·策略模式
therese_1008615 小时前
客户端架构:为什么、什么时候、怎么做
设计模式·安卓·鸿蒙