You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Quarkus CDI TenantScoped上下文在应用中未生效问题排查

自定义TenantScoped上下文失效问题排查与解决

核心问题分析

你遇到的问题核心原因是Quarkus对final类型(如AtomicLong)无法生成CDI代理,导致自定义TenantScoped上下文无法拦截实例的创建与获取,最终被降级为ApplicationScoped处理。Quarkus的CDI实现依赖代理类来实现自定义Scope的上下文切换,而final类无法被继承生成代理,因此会跳过自定义上下文逻辑。

具体解决步骤

1. 替换final类型为可代理的包装类

将AtomicLong包装在一个非final的自定义类中,让Quarkus能够生成代理类:

public class TenantAtomicLong {
    private final AtomicLong value = new AtomicLong(-1);

    public long get() {
        return value.get();
    }

    public void set(long newValue) {
        value.set(newValue);
    }
}

然后修改Produces方法和注入点:

@ApplicationScoped
public class Service {

    @Inject
    @Named("tenantLong")
    TenantAtomicLong tenantScopedLong;

    public void setLong(long number) {
        tenantScopedLong.set(number);
    }

    public long getLong() {
        return tenantScopedLong.get();
    }

    @TenantScoped
    @Named("tenantLong")
    @Produces
    TenantAtomicLong tenantLong() {
        return new TenantAtomicLong();
    }
}

2. 确保上下文激活逻辑正确

自定义上下文需要在请求生命周期内被激活/销毁,检查你的TenantScopeContext实现是否包含以下逻辑:

  • 实现ActivatableContext接口,确保上下文能被正确激活
  • 通过Quarkus扩展绑定生命周期事件,比如在请求开始时调用activate(),结束时调用deactivate()

示例激活逻辑(扩展构建步骤):

@BuildStep
void registerContextActivator(BuildProducer<ServletFilterBuildItem> filterProducer) {
    filterProducer.produce(ServletFilterBuildItem.builder("TenantContextFilter", TenantContextFilter.class)
            .order(100)
            .build());
}

对应的Filter实现:

public class TenantContextFilter implements Filter {
    @Inject
    TenantScopeContext tenantContext;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            tenantContext.activate(); // 根据实际需求传递上下文参数
            chain.doFilter(request, response);
        } finally {
            tenantContext.deactivate();
        }
    }
}

3. 验证Scope注册的正确性

检查你的构建步骤是否在正确的阶段注册上下文:

  • ContextRegistrationPhaseBuildItem是正确的注册阶段,但确保没有其他扩展覆盖了你的Scope配置
  • 确认CustomScopeBuildItem正确声明了TenantScoped.class,且没有重复注册的情况

额外注意点

  • 避免对final类、基本类型或JDK核心不可变类型使用自定义Scope,这类类型无法生成CDI代理
  • 单元测试中可能因为环境简化,代理生成逻辑被绕过,导致上下文正常工作,但实际应用中严格遵循代理规则

内容的提问来源于stack exchange,提问作者Herr Derb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:37:46