反射与aop拦截器的核心关系在于:反射是实现aop拦截器的技术基础,通过动态获取方法信息并调用method.invoke()在目标方法执行前后插入横切逻辑,从而达成解耦。

什么是反射与AOP拦截器的核心关系
反射是Java在运行时动态获取类信息、调用方法、访问字段的能力;AOP(面向切面编程)则关注将横切逻辑(如日志、权限、事务)从主业务中解耦。手动实现AOP拦截器,本质就是利用反射“劫持”目标方法的执行流程——在真正调用前、后或异常时插入自定义逻辑。
关键步骤:用反射构建可插拔的方法拦截器
不依赖Spring AOP或字节码增强,仅靠java.lang.reflect就能完成基础拦截。核心在于:用代理对象包装目标实例,重写方法调用逻辑,再通过反射触发原方法。
- 定义拦截器接口:统一前置(before)、后置(after)、异常(afterThrowing)钩子
-
编写动态代理类:实现
InvocationHandler,在invoke()中判断是否需要拦截、执行钩子、再用Method.invoke()调用原方法 -
支持注解驱动:例如定义
@Log,在invoke中检查目标方法是否有该注解,有则执行日志逻辑 -
保留原始调用上下文:把
Method、参数、返回值、异常等作为钩子方法的入参,便于日志记录或审计
一个极简但可运行的示例
假设有一个服务类UserService和方法getUserById(int id),我们想在调用前后打印日志:
- 创建
SimpleAopProxy类,接收目标对象和拦截器实例 - 在
invoke()中先调interceptor.before(method, args) - 捕获异常,正常则调
method.invoke(target, args),再调after();异常则调afterThrowing(e) - 用
Proxy.newProxyInstance()生成代理,接口类型需与目标类实现的接口一致(JDK动态代理限制)
注意事项与局限性
纯反射实现的拦截器轻量、透明,但也有明显边界:
- 只能代理接口实现类(JDK Proxy限制),无法代理普通类(需CGLIB或字节码工具)
- 无法拦截
private、static、final方法——反射可访问private,但代理机制本身不覆盖它们 - 性能略低于编译期织入,每次调用多一层反射开销,高频场景建议缓存
Method对象或使用MethodHandle - 异常处理需显式透出,避免吞掉原始异常导致调试困难










