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 都是基于类似的理念,只不过使用了更底层的代理机制和字节码增强。
相关推荐
迅猛龙办公室5 小时前
Python输出当前计算机的系统日期和时间
开发语言·前端·python
小狼154545 小时前
浏览器扩展脚本为什么有时候不生效:注入时机、iframe 和单页路由,多多开票助手
前端·chrome
じòぴé南冸じょうげん6 小时前
油猴脚本突然发现变成灰色了,无法使用?页面不生效?刷新页面没反应?
前端
步行cgn7 小时前
Spring 全注解开发详解
java·后端·spring
Csvn7 小时前
组合式 API(Composition API)
前端
火柴就是我8 小时前
Android 打包报错 25.0.3
android·前端
BD_Marathon8 小时前
消息对象中字段的说明
java·前端·python
八荒启·交互动画8 小时前
Web特效025—用 Canvas 2D 做Web特效的定义与边界:这支画笔能做到哪一步
前端·webgl·网页特效·八荒启-交互动画·八荒启
Ai-_Man8 小时前
您您这可以把Dola的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。用AI导出鸭,答案是可以的
开发语言·前端·人工智能·小程序
excel9 小时前
Nuxt 中使用 useHead 优化 SEO 与 GEO
前端