设计模式 - 代理模式

发布于:2025-04-09 ⋅ 阅读:(30) ⋅ 点赞:(0)

代理模式

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

1.静态代理

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

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反射机制实现,它需要被代理对象实现一个接口。


/**
 * 代理对象 实现 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动态代理是针对类进行代理的,它通过继承目标类创建子类,并重写目标类的方法。

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();
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到