JFinal AOPJFinal AOP
源码
Tio Boot
GitHub
源码
Tio Boot
GitHub
  • JFinal AOP
  • JFinal-aop
  • Aop 工具类
  • 配置
  • 独立使用 JFinal Aop
  • @AImport
  • 自定义注解拦截器
  • 原理解析

自定义注解拦截器

  • registerInterceptor 的作用
    • ✅ 将 “业务注解” 自动绑定到拦截器
  • 一、注册拦截器
    • 示例:
  • 二、定义事务注解
  • 三、实现拦截器
    • 为什么使用 Aop.get?
  • 四、业务代码使用方式
    • 不推荐:
    • 推荐:
  • 五、运行原理(重要)
    • 分为两个阶段:
    • 🔥 阶段 1:生成代理类(启动时)
    • 🔥 阶段 2:方法调用时
  • 六、AopClear 仍然有效
    • 清除规则:
  • 七、强烈建议的最佳实践
    • ⭐ 1. 永远使用语义化注解
    • ⭐ 2. registerInterceptor 统一放 Boot 阶段
    • ⭐ 3. 一个注解只做一件事
  • 八、registerInterceptor vs AopBefore
    • registerInterceptor:
    • AopBefore:
  • 九、性能说明
  • 十、一句话总结

使用 AopInterceptorManager.me().registerInterceptor 实现自定义注解拦截器

在基于 JFinal AOP 的开发中,我们通常使用:

@AopBefore(SomeInterceptor.class)

来为方法添加拦截器。

但这种方式有一个明显问题:

👉 业务语义不清晰

例如事务:

@AopBefore(TransactionInterceptor.class)

从代码上完全看不出:

“这是一个事务方法”

这也是为什么 Spring、Micronaut、Quarkus 等框架都提供:

@Transactional

这种语义化注解。


registerInterceptor 的作用

AopInterceptorManager.me().registerInterceptor(...) 的目标是:

✅ 将 “业务注解” 自动绑定到拦截器

例如:

@ATransactional  ->  TransactionInterceptor

让开发者只关注:

“这是事务方法”

而不是:

“这个方法需要某个技术型拦截器”


一、注册拦截器

建议在 Boot 配置阶段注册。

示例:

package demo.jooq.config;

import nexus.io.context.BootConfiguration;
import nexus.io.jfinal.aop.AopInterceptorManager;

import demo.jooq.tx.ATransactional;
import demo.jooq.tx.TransactionInterceptor;

public class JooqBootConfig implements BootConfiguration {

  @Override
  public void config() throws Exception {

    // 注解 -> 拦截器 绑定
    AopInterceptorManager.me().registerInterceptor(ATransactional.class, TransactionInterceptor.class);
  }
}

启动:

TioApplication.run(JooqApp.class, new JooqBootConfig(), args);

⚠️ 必须在应用启动早期注册!

原因:

ProxyGenerator 在生成代理类时,需要提前知道哪些方法存在拦截器。

如果注册过晚:

👉 方法可能不会生成代理 👉 拦截器将完全不生效


二、定义事务注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ATransactional {
}

建议改为:

@Target({ElementType.METHOD, ElementType.TYPE})

这样可以支持:

  • 方法级事务
  • 类级事务(整个 Service)

三、实现拦截器

public class TransactionInterceptor implements AopInterceptor {

  @Override
  public void intercept(AopInvocation inv) {

    TransactionManager txManager =Aop.get(TransactionManager.class);

    txManager.tx(() -> {
      inv.invoke();
    });
  }
}

为什么使用 Aop.get?

而不是:

new TransactionManager()

因为:

✅ 支持依赖注入 ✅ 支持代理 ✅ 生命周期统一


四、业务代码使用方式

不推荐:

@AopBefore(TransactionInterceptor.class)
public void changePassword(...) {
}

技术味太重。


推荐:

@ATransactional
public void changePassword2(String loginName, String newPassword) {
  systemAdminDao.updatePassword(loginName, newPassword);
}

可读性极强:

这是一个事务方法。


五、运行原理(重要)

很多人会误以为:

registerInterceptor 是运行时才生效。

实际上:

分为两个阶段:


🔥 阶段 1:生成代理类(启动时)

ProxyGenerator 会判断:

方法是否存在拦截器?

包括:

  • @AopBefore
  • 全局拦截器
  • registerInterceptor 映射注解

如果存在:

👉 才生成代理方法。

否则:

👉 直接调用原方法。

这一步极其关键。


🔥 阶段 2:方法调用时

代理代码类似:

AopInvocation inv = new AopInvocation(...);
inv.invoke();

然后:

AopInterceptorManager
    -> 构建拦截器链
    -> 顺序执行

TransactionInterceptor 就在这里执行。


六、AopClear 仍然有效

例如:

@AopClear(TransactionInterceptor.class)
public void queryOnly() {
}

效果:

移除事务拦截器。

即使:

@ATransactional

在类上声明。


清除规则:

位置行为
class 无参清除 global 拦截器
class 带参从 global 中清除指定拦截器
method 无参只保留 method 拦截器(含注解映射的拦截器)
method 带参从 global、class 中清除指定拦截器

注意:方法上通过注解映射得到的拦截器属于 method 层,@AopClear 写在同一方法上不能清除它。

与使用 @AopBefore 时完全一致。

无需额外配置。


七、强烈建议的最佳实践

⭐ 1. 永远使用语义化注解

不要写:

@AopBefore(CacheInterceptor.class)

写:

@ACacheable

⭐ 2. registerInterceptor 统一放 Boot 阶段

不要在:

  • Service
  • DAO
  • Controller

中注册。

否则代理可能已经生成。


⭐ 3. 一个注解只做一件事

错误:

@ATransactional + @Cache + @Retry

正确:

  • @ATransactional
  • @ACacheable
  • @Retryable

组合使用。


八、registerInterceptor vs AopBefore

registerInterceptor:

✅ 推荐用于:

  • 事务
  • 缓存
  • 限流
  • 重试
  • 审计日志

即:

具有明确业务语义的能力


AopBefore:

适合:

  • 临时拦截器
  • 内部调试
  • 框架级增强

但不建议直接暴露给业务层。


九、性能说明

很多人担心:

注解映射会不会降低性能?

答案:

几乎不会。

原因:

  • 映射只在启动时解析一次
  • 拦截器实例是单例
  • 方法调用走的是生成代码(非反射)

性能接近手写代理。


十、一句话总结

registerInterceptor 的本质是:让 AOP 从“技术驱动”升级为“业务语义驱动”。

让代码从:

怎么实现?

变为:

这段代码在做什么?

这就是现代 AOP 的设计方向。


Edit this page
最近更新: 2026/11/5 01:47
Contributors: Tong Li, Claude Opus 5.5
Prev
@AImport
Next
原理解析