代理模式增强拒绝策略

发布于:2025-09-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

代理模式增强拒绝策略

一.静态代理与动态代理

1.概述

代理类型 含义 代码实现 典型应用
静态代理 代理类在编译时已经写好,代理对象和被代理对象的代码明确存在 手写代理类,代理类实现同样接口或继承同样父类,组合被代理对象 日志、权限控制、事务处理等
动态代理 代理类在运行时通过反射动态生成,代理对象由系统自动创建 利用 Java Proxy 类和 InvocationHandler 反射机制 AOP、RPC 框架、接口增

2.原理与使用示例

静态代理:

静态代理是开发者事先编写一个代理类,代理类实现目标接口,持有目标对象引用,调用代理类方法时,代理类先做一些增强逻辑,再调用目标对象对应方法。

// 目标接口
public interface Service {
    void execute();
}

// 目标实现
public class ServiceImpl implements Service {
    @Override
    public void execute() {
        System.out.println("执行核心业务逻辑");
    }
}

// 静态代理类
public class ServiceProxy implements Service {
    private final Service target;

    public ServiceProxy(Service target) {
        this.target = target;
    }

    @Override
    public void execute() {
        System.out.println("执行前置增强");
        target.execute();
        System.out.println("执行后置增强");
    }
}

优点 缺点
逻辑清晰,易理解 每个接口需要写一个代理类,代码臃肿
调试方便,堆栈清晰 不灵活,扩展性差,新增接口需要增加代理类
适合接口少且业务简单 增加代码维护成本
动态代理:

动态代理是在运行时动态生成代理类,通过反射机制调用代理逻辑,实现统一代理。核心组件:

  • java.lang.reflect.Proxy:用于创建动态代理实例。
  • java.lang.reflect.InvocationHandler:代理方法调用的处理器。

代理对象实现了目标接口,所有方法调用都会被 InvocationHandlerinvoke 方法拦截处理。

关键接口和类

InvocationHandler

public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
  • proxy:代理对象本身,一般不直接调用。
  • method:当前被调用的方法。
  • args:方法参数。

Proxy

public class Proxy {
    public static Object newProxyInstance(
            ClassLoader loader,
            Class<?>[] interfaces,
            InvocationHandler h) {
        // 生成代理类字节码,返回代理对象实例
    }
}
  • loader:类加载器,代理类由它加载。
  • interfaces:代理类实现的接口列表。
  • h:方法调用处理器。

实例:

public interface Service {
    void execute();
}

public class ServiceImpl implements Service {
    @Override
    public void execute() {
        System.out.println("执行核心业务");
    }
}

public class ServiceInvocationHandler implements InvocationHandler {

    private final Object target;

    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增强");
        Object result = method.invoke(target, args);
        System.out.println("后置增强");
        return result;
    }
}

调用:

Service target = new ServiceImpl();
Service proxy = (Service) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    new Class[]{Service.class},
    new ServiceInvocationHandler(target)
);
proxy.execute();

注意点:

优点 缺点
代理类无需提前编写,灵活 只能代理接口(JDK 动态代理)
统一拦截所有方法,减少代码量 调试难,异常堆栈不直观
运行时生成,支持高度动态 性能略低于静态代理
易扩展,广泛应用于 AOP、RPC 不支持代理普通类(需 CGLIB)

如果只想拦截特定方法:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if ("targetMethodName".equals(method.getName())) {
        // 只增强指定方法
        System.out.println("执行增强逻辑");
    }
    // 调用目标对象方法
    return method.invoke(target, args);
}

二.动态代理增强

@AllArgsConstructor
public class RejectedProxyInvocationHandler implements InvocationHandler {

    private final Object target;
    private final String threadPoolId;
    private final AtomicLong rejectCount;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        rejectCount.incrementAndGet();

        // TODO 触发拒绝策略异常告警
        try {
            return method.invoke(target, args);
        } catch (InvocationTargetException ex) {
            throw ex.getCause();
        }
    }
}

在我们的自定义线程池内使用代理拒绝策略

public OneThreadExecutor(
            @NonNull String threadPoolId,
            int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            @NonNull TimeUnit unit,
            @NonNull BlockingQueue<Runnable> workQueue,
            @NonNull ThreadFactory threadFactory,
            @NonNull RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);

        // 通过动态代理设置拒绝策略执行次数
        RejectedExecutionHandler rejectedProxy = (RejectedExecutionHandler) Proxy
                .newProxyInstance(
                        handler.getClass().getClassLoader(),
                        new Class[]{RejectedExecutionHandler.class},
                        new RejectedProxyInvocationHandler(handler, threadPoolId, rejectCount)
                );
        setRejectedExecutionHandler(rejectedProxy);

        // 设置动态线程池扩展属性:线程池 ID 标识
        this.threadPoolId = threadPoolId;
    }

三.静态代理增强

public class RejectCountingHandler implements RejectedExecutionHandler {

    private final RejectedExecutionHandler delegate;
    private final String threadPoolId;
    private final AtomicLong rejectCount;

    public RejectCountingHandler(RejectedExecutionHandler delegate, String threadPoolId, AtomicLong rejectCount) {
        this.delegate = delegate;
        this.threadPoolId = threadPoolId;
        this.rejectCount = rejectCount;
    }

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        rejectCount.incrementAndGet();

        // 可插入报警逻辑
        // log.warn("[线程池拒绝] id={},累计拒绝次数={}", threadPoolId, rejectCount.get());

        delegate.rejectedExecution(r, executor); // 调用原始拒绝策略
    }
}

在我们的自定义线程池内使用代理拒绝策略

RejectedExecutionHandler rejectedProxy = new RejectCountingHandler(handler, threadPoolId, rejectCount);