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 都是基于类似的理念,只不过使用了更底层的代理机制和字节码增强。