500. Java 反射 - 使用注解创建拦截器
1. 什么是拦截器 (Interceptor)?
拦截器是一种横切关注点处理机制,在很多框架中非常常见,比如 Java EE、Jakarta EE、Spring AOP 等。
核心思想:
- 业务方法本身只关心业务逻辑。
- 拦截器在业务方法执行前后介入,完成其他功能(日志、校验、安全、事务、异常处理等)。
- 通过注解声明要拦截的方法,使得代码简洁、解耦。
👉 可以把拦截器想象成“门卫”:
- 方法就是门后的人,
- 拦截器决定是否允许进门、是否需要额外检查,还可以在出去时再加一些操作。
2. 我们要实现的目标
我们设计一个简单的机制:
- 在业务方法上打一个注解
@Intercept。 - 注解中指定一个拦截器类。
- 当调用业务方法时,实际执行的是拦截器里的逻辑,而不是直接运行业务方法。
3. 定义拦截器注解
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Intercept {
Class<? extends MethodInterceptor> value();
}
👉 这里我们定义了一个 @Intercept 注解:
-
@Target(ElementType.METHOD):只能用在方法上。 -
value():用来指定一个拦截器类,必须实现我们定义的MethodInterceptor接口。
4. 定义拦截器接口
public interface MethodInterceptor {
Object invoke(Method method, Object target, Object[] args) throws Exception;
}
说明:
-
method→ 被拦截的方法对象 -
target→ 被调用的目标对象 -
args→ 调用方法时传入的参数
5. 编写一个具体拦截器
比如我们要做一个简单的 日志拦截器:
public class LoggingInterceptor implements MethodInterceptor {
@Override
public Object invoke(Method method, Object target, Object[] args) throws Exception {
System.out.println("👉 调用方法: " + method.getName());
System.out.println("👉 参数: " + Arrays.toString(args));
Object result = method.invoke(target, args);
System.out.println("👉 返回值: " + result);
return result;
}
}
6. 在业务类中使用拦截器
public class UserService {
@Intercept(LoggingInterceptor.class)
public String sayHello(String name) {
return "Hello, " + name;
}
}
7. 执行拦截逻辑
我们用反射来检查方法是否带有 @Intercept 注解,如果有,则执行对应的拦截器。
public class InterceptorRunner {
public static void run(Object target, String methodName, Object... args) throws Exception {
Method method = target.getClass().getMethod(methodName, String.class);
if (method.isAnnotationPresent(Intercept.class)) {
Intercept annotation = method.getAnnotation(Intercept.class);
MethodInterceptor interceptor = annotation.value().getDeclaredConstructor().newInstance();
interceptor.invoke(method, target, args);
} else {
method.invoke(target, args);
}
}
public static void main(String[] args) throws Exception {
UserService service = new UserService();
run(service, "sayHello", "Alice");
}
}
8. 运行结果
👉 调用方法: sayHello
👉 参数: [Alice]
👉 返回值: Hello, Alice
9. 总结
- 拦截器让我们可以在方法调用前后执行额外逻辑。
- 注解 + 反射提供了一种轻量级的方式来实现类似 AOP 的功能。
- 在企业框架里,这种思想被广泛用于:
- 日志打印
- 参数校验
- 安全检查
- 事务管理
- 异常统一处理