503. Java 反射 - 编写 ServiceFactory 类

文章目录

  • [503. Java 反射 - 编写 ServiceFactory 类](#503. Java 反射 - 编写 ServiceFactory 类)
    • [1. 设计目标](#1. 设计目标)
    • [2. 核心实现代码](#2. 核心实现代码)
    • [3. 示例说明](#3. 示例说明)
      • [(1) 带拦截器的服务](#(1) 带拦截器的服务)
      • [(2) 没有拦截器的服务](#(2) 没有拦截器的服务)
      • [(3) 测试调用](#(3) 测试调用)
      • [(4) 运行结果](#(4) 运行结果)
    • 4.总结

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 都是基于类似的理念,只不过使用了更底层的代理机制和字节码增强。
相关推荐
BK贝壳28 分钟前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
2601_966949652 小时前
如何根据研究的起止时间截取分钟级行情?Python 实战与 QuantDash 数据处理指南
开发语言·python·pandas·量化交易·1024程序员节·股票数据·quantdash
晨曦中的暮雨4 小时前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
喵了几个咪5 小时前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
程序员清风5 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
文丑颜不良啊5 小时前
LeetCode876~900题目解析
java·leetcode
aloha_7896 小时前
Java 基础、集合、异常与 JUnit 5 速查
java·junit·sqlserver
在世修行6 小时前
智学文枢:页面切换与跨页数据预填
python·桌面应用·signal·1024程序员节·pyside·跨页跳转·状态预填
知守观7 小时前
设计模式实战:从真实老项目中看标准模板方法与工厂的落地
java·spring·设计模式
2601_962885727 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python