设计模式 - 代理模式

代理模式

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

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();
    }
}
相关推荐
大鹏dapeng21 分钟前
使用gone v2 的 Provider 机制升级改造 goner/xorm 的过程记录
后端·设计模式·go
快乐源泉24 分钟前
【设计模式】参数校验逻辑复杂,代码长?用责任链
后端·设计模式·go
天堂的恶魔9461 小时前
C++项目 —— 基于多设计模式下的同步&异步日志系统(2)(工厂模式)
开发语言·c++·设计模式
小猪乔治爱打球1 小时前
[Golang修仙之路] 策略模式
设计模式
chushiyunen2 小时前
设计模式-观察者模式和发布订阅模式区别
观察者模式·设计模式
浅陌sss2 小时前
设计模式 --- 观察者模式
设计模式
程序员JerrySUN3 小时前
设计模式 Day 9:命令模式(Command Pattern)完整讲解与实战应用
设计模式·命令模式
小马爱打代码13 小时前
设计模式:依赖倒转原则 - 依赖抽象,解耦具体实现
设计模式
Koma-forever13 小时前
java设计模式-适配器模式
java·设计模式·适配器模式
自在如风。15 小时前
Java 设计模式:原型模式详解
java·设计模式·原型模式