callbackfilter是调度器,通过accept()返回索引值决定各方法调用callbacks数组中对应下标的拦截器,实现不同方法走不同增强逻辑。

直接结论:用 CallbackFilter 配合 setCallbacks(),就能让同一个代理对象对不同方法走不同的拦截器(比如一个方法走事务逻辑、另一个走日志、第三个跳过拦截)。它不是“增强版的 MethodInterceptor”,而是调度器——决定「哪个方法该进哪个回调」。
CallbackFilter.accept() 返回值到底代表什么
它返回的是整数索引,对应你传给 enhancer.setCallbacks(new Callback[]{...}) 的数组下标。不是布尔开关,也不是自定义状态码。
- 返回
0→ 调用callbacks[0](比如MethodInterceptor) - 返回
1→ 调用callbacks[1](比如NoOp.INSTANCE,即不拦截直接放行) - 返回
2→ 调用callbacks[2](比如FixedValue,固定返回值) - 如果返回越界(如
3但数组只有 2 个元素),运行时报ArrayIndexOutOfBoundsException
为什么不能只用 MethodInterceptor 里 if-else 判断方法名
可以,但不推荐——尤其当拦截逻辑差异大、或部分方法要完全绕过代理时。
-
MethodInterceptor.intercept()总会执行,哪怕你最后调用methodProxy.invokeSuper();而NoOp或FixedValue是彻底跳过拦截链,性能更高 - 事务、缓存、权限等横切关注点常需独立生命周期管理(如事务拦截器要控制
TransactionStatus),混在同一个intercept()里易耦合、难复用 - Spring AOP 底层就靠这套多回调 + 过滤机制支撑 @Transactional、@Cacheable 等多个注解共存
实际写法中三个容易踩的坑
常见错误不是语法错,而是语义错或配置漏:
- 忘记调用
enhancer.setCallbackFilter(...):即使写了CallbackFilter,没 set 就等于没装调度器,所有方法默认走callbacks[0] -
accept()方法里没覆盖所有方法:比如只判断了"save"和"delete",但类里还有"getById",它就会 fallback 到你return的默认值(常是0),导致意外拦截 - 回调数组长度和
accept()返回值范围不匹配:例如数组只有 2 个元素,但某个分支返回2,启动时不会报错,调用时才崩
最简验证示例:一个类有 read()(走日志)、write()(走事务)、ping()(不拦截)。只要确保 accept() 对三者分别返回 0、1、2,且 callbacks 数组长度为 3,就稳了。复杂点在于业务逻辑分离,不在字节码层面。










