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

如何在DGS+Spring Boot框架下不通过传参访问频繁实例化的对象

可行的线程安全实现方案

有两种成熟的实现方式可以满足需求,无需在方法签名中传递上下文参数,同时保证线程安全:

方案1:基于ThreadLocal实现上下文持有者

改造原有RequestContextHolder,使用ThreadLocal存储上下文,利用ThreadLocal的线程隔离特性保证线程安全,同时配合DGS请求拦截器完成上下文的设置和清理,避免内存泄漏。

改造后的RequestContextHolder代码

@Component
public class RequestContextHolder {
    private static final ThreadLocal<RequestContext> CONTEXT_HOLDER = new ThreadLocal<>();

    public void setRequestContext(RequestContext context) {
        CONTEXT_HOLDER.set(context);
    }

    public RequestContext getRequestContext() {
        return CONTEXT_HOLDER.get();
    }

    public void clear() {
        CONTEXT_HOLDER.remove();
    }
}

新增DGS请求拦截器完成上下文绑定

实现DGS自带的DgsRequestInterceptor接口,在请求预处理阶段将自定义上下文存入ThreadLocal,请求结束后清理:

@Component
public class ContextBindInterceptor implements DgsRequestInterceptor {
    private final RequestContextHolder requestContextHolder;

    public ContextBindInterceptor(RequestContextHolder requestContextHolder) {
        this.requestContextHolder = requestContextHolder;
    }

    @Override
    public void preProcess(DgsRequestData requestData, DataFetchingEnvironment env) {
        MyCustomContext dgsContext = DgsContext.getCustomContext(env);
        RequestContext requestContext = new RequestContext();
        // 此处完成dgs上下文到你自定义RequestContext的属性复制
        requestContext.setRoles(dgsContext.getRoles());
        requestContextHolder.setRequestContext(requestContext);
    }

    @Override
    public void postProcess(DgsRequestData requestData, Object result) {
        // 必须清理,防止线程复用导致的上下文串用和内存泄漏
        requestContextHolder.clear();
    }
}

完成配置后,你可以在任意业务类中直接注入RequestContextHolder,调用getRequestContext()即可获取当前请求的上下文,无需传递参数。


方案2:基于Spring请求作用域Bean实现(更简洁)

利用Spring原生的request作用域,直接将上下文定义为每个请求独立实例的Bean,Spring会自动通过代理保证单例Bean注入时拿到当前请求的上下文实例,无需手动处理ThreadLocal。

定义请求级上下文Bean

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestContext {
    // 自定义上下文属性
    private List<String> roles;
    // 其他用户/权限相关属性
    // getter和setter
}

新增DGS拦截器完成上下文赋值

@Component
public class ContextInitInterceptor implements DgsRequestInterceptor {
    // 注入的是代理对象,实际指向当前请求对应的RequestContext实例
    private final RequestContext requestContext;

    public ContextInitInterceptor(RequestContext requestContext) {
        this.requestContext = requestContext;
    }

    @Override
    public void preProcess(DgsRequestData requestData, DataFetchingEnvironment env) {
        MyCustomContext dgsContext = DgsContext.getCustomContext(env);
        // 直接给当前请求的上下文赋值
        requestContext.setRoles(dgsContext.getRoles());
        // 其他属性赋值
    }
}

该方案使用更简单,你可以在任意需要上下文的地方直接注入RequestContext即可使用,Spring会自动管理Bean的生命周期,不需要手动清理,天然线程安全。


注意事项

如果业务存在异步逻辑,需要额外配置线程池的TaskDecorator完成上下文在异步线程的传递,同步场景下上述两种方案可直接使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:15:04