503. Java 反射 - 编写 ServiceFactory 类

503. Java 反射 - 编写 ServiceFactory 类

1. 设计目标

ServiceFactory 的职责是 统一拦截服务方法的调用

  • 它接收:服务类、方法名、方法参数
  • 自动创建服务实例。
  • 找到目标方法,并判断是否带有 @Intercept 注解。
  • 如果有注解 → 使用对应的拦截器来执行方法逻辑。
  • 如果没有注解 → 直接调用方法。

这样我们就实现了一个简化版的 拦截器机制


2. 核心实现代码

java 复制代码
public class ServiceFactory {
    public static <T, R> R invoke(
            Class<? extends T> serviceClass, String methodName, Object... arguments) {
        try {
            // ✅ 1. 创建服务实例(要求必须有无参构造器)
            T service = serviceClass.getConstructor().newInstance();

            // ✅ 2. 确定参数类型数组,用于定位目标方法
            Class<?>[] parameterClasses =
                    Arrays.stream(arguments).map(Object::getClass).toArray(Class<?>[]::new);
            Method method = serviceClass.getDeclaredMethod(methodName, parameterClasses);

            // ✅ 3. 判断方法上是否存在 @Intercept 注解
            if (method.isAnnotationPresent(Intercept.class)) {
                Intercept intercept = method.getDeclaredAnnotation(Intercept.class);

                // 获取拦截器类,并实例化
                Class<? extends Interceptor<T, R>> interceptorClass =
                        (Class<? extends Interceptor<T, R>>) intercept.value();
                Interceptor<T, R> interceptor = interceptorClass.getConstructor().newInstance();

                // ✅ 4. 使用拦截器执行方法
                return interceptor.intercept(service, method, arguments);
            } else {
                // ✅ 5. 没有注解 → 直接反射调用
                return (R) method.invoke(service, arguments);
            }
        } catch (InstantiationException | IllegalAccessException |
                 InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

3. 示例说明

(1) 带拦截器的服务

java 复制代码
public class SomeInterceptedService {
    @Intercept(MessageInterceptor.class)
    public String message(String input) {
        return input.toUpperCase();
    }
}

(2) 没有拦截器的服务

java 复制代码
public class SomeNonInterceptedService {
    public String message(String input) {
        return input.toUpperCase();
    }
}

(3) 测试调用

java 复制代码
public class Main {
    public static void main(String[] args) {
        String interceptedOutput =
                ServiceFactory.invoke(SomeInterceptedService.class, "message", "Hello");
        System.out.println("Intercepted output = " + interceptedOutput);

        String nonInterceptedOutput =
                ServiceFactory.invoke(SomeNonInterceptedService.class, "message", "Hello");
        System.out.println("Non intercepted output = " + nonInterceptedOutput);
    }
}

(4) 运行结果

java 复制代码
Intercepted output = HELLO [was intercepted]
Non intercepted output = HELLO

4.总结

  • 统一入口 :不管有没有拦截器,ServiceFactory.invoke() 都能完成方法调用。
  • 灵活扩展:不同方法可以使用不同的拦截器(比如日志拦截器、权限拦截器、缓存拦截器)。
  • 类型不安全:由于反射和强制类型转换,编译期无法保证安全性 → 运行时可能抛出异常。
  • 对比实际框架:Spring AOP、Jakarta EE Interceptor 都是基于类似的理念,只不过使用了更底层的代理机制和字节码增强。
相关推荐
高频因子挖掘机1 小时前
QuantDash 成交量单位统一实战:从“手”到“股”的跨市场量化数据清洗全流程
后端·算法·github
赵大仁1 小时前
AI 限流 UX 设计:排队、降级、告知与用户预期管理
前端·ai·限流·用户体验·产品设计
码农看码1 小时前
Spring Boot 启动到响应:一个 HTTP 请求是怎么走到 Controller 的?
后端
__sjfzllv___2 小时前
在职前端Leader学习/转行 AI Agent -DAY37
前端
用户2181697049302 小时前
Flutter (二十二) GlobalKey
前端
薛定谔的算法2 小时前
NestJS:让 Node.js 后端告别「野路子」
后端·node.js·nestjs
fightcrap2 小时前
DeepSeek Harness:Cordis 插件树与 Agent 主链路
人工智能·后端·程序员
用户2181697049302 小时前
Flutter (二十一) 下拉刷新,加载更多
前端
程序猿DD2 小时前
OctaFuse Gateway 2.7.0:按星期计价、用户级模型折扣、百炼ASR模型支持优化
后端·agent