文章目录
- 501. Java 反射 - 使用注解与接口设计拦截器
- 1. 为什么要定义拦截器接口?
- 接口定义
- 2. 定义拦截注解
- 3. 编写业务服务类
- 4. 编写一个拦截器实现类
- 5. 设计一个 ServiceFactory 来统一调用
- 6. 测试拦截功能
- 7. 总结
501. Java 反射 - 使用注解与接口设计拦截器
1. 为什么要定义拦截器接口?
我们希望在调用某个方法前后插入自定义逻辑(如日志、安全校验、数据转换等)。为了让这个机制通用化,我们定义一个拦截器接口,所有拦截器都必须实现它。
接口定义
publicinterfaceInterceptor<T,R>{Rintercept(TinterceptedObject,Methodmethod,Object...arguments);}T interceptedObject→ 被拦截的对象(例如一个 Service 实例)。Method method→ 被拦截的方法。Object... arguments→ 方法调用时传入的参数。R→ 方法的返回值类型。
👉 使用泛型保证了接口的灵活性,既能拦截返回String的方法,也能拦截返回User的方法。
2. 定义拦截注解
我们需要一个注解来标记哪些方法需要被拦截,以及指定使用哪个拦截器。
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceIntercept{Class<?extendsInterceptor<?,?>>value();}@Target(ElementType.METHOD)→ 注解只能放在方法上。@Retention(RetentionPolicy.RUNTIME)→ 在运行时依然保留,供反射使用。value()→ 指定具体的拦截器类。
3. 编写业务服务类
publicclassSomeInterceptedService{@Intercept(MessageInterceptor.class)publicStringmessage(Stringinput){returninput.toUpperCase();}}- 方法
message()被@Intercept标记。 - 拦截器类
MessageInterceptor将会替代message()的直接执行。
4. 编写一个拦截器实现类
我们来实现一个简单的拦截器,它会在调用message()前后打印日志。
publicclassMessageInterceptorimplementsInterceptor<SomeInterceptedService,String>{@OverridepublicStringintercept(SomeInterceptedServiceservice,Methodmethod,Object...arguments){System.out.println("👉 Before invoking "+method.getName());try{// 真实调用被拦截的方法Stringresult=(String)method.invoke(service,arguments);System.out.println("👉 After invoking, result = "+result);returnresult;}catch(Exceptione){thrownewRuntimeException("Interceptor caught exception",e);}}}运行逻辑:
- 在方法执行前打印日志。
- 执行目标方法 (
method.invoke)。 - 在方法执行后打印返回值。
5. 设计一个 ServiceFactory 来统一调用
我们需要一个工厂类ServiceFactory来读取注解并执行拦截逻辑。
publicclassServiceFactory{@SuppressWarnings("unchecked")publicstatic<T>Objectinvoke(Class<T>serviceClass,StringmethodName,Object...args)throwsException{Tservice=serviceClass.getDeclaredConstructor().newInstance();Methodmethod=serviceClass.getMethod(methodName,String.class);if(method.isAnnotationPresent(Intercept.class)){InterceptinterceptAnnotation=method.getAnnotation(Intercept.class);Class<?extendsInterceptor<?,?>>interceptorClass=interceptAnnotation.value();Interceptor<T,?>interceptor=(Interceptor<T,?>)interceptorClass.getDeclaredConstructor().newInstance();returninterceptor.intercept(service,method,args);}else{returnmethod.invoke(service,args);}}}👉 流程:
- 通过反射创建服务实例。
- 找到方法并检查是否有
@Intercept。 - 如果有,执行对应的拦截器逻辑。
- 如果没有,直接调用原始方法。
6. 测试拦截功能
publicclassMain{publicstaticvoidmain(String[]args)throwsException{Stringoutput=(String)ServiceFactory.invoke(SomeInterceptedService.class,"message","Hello");System.out.println("Final output = "+output);}}运行结果:
👉Beforeinvoking message 👉Afterinvoking,result=HELLOFinaloutput=HELLO7. 总结
Interceptor<T, R>定义了拦截器的通用接口。@Intercept注解用来声明哪些方法需要拦截,以及由哪个拦截器处理。- 业务类通过注解与拦截器解耦,不需要手动调用拦截器。
ServiceFactory承担了框架的角色,把注解与拦截器绑定在一起。