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

Spring Boot注入request作用域Bean报ScopeNotActiveException如何解决

问题根因

报错的核心原因是 request作用域Bean的调用时机不合法:

  • com.common.Security 被声明为request作用域,只有HTTP请求处于活跃状态时Spring才会生成对应的实例,每个请求对应独立实例
  • 你虽然已经为Security配置了ScopedProxyMode.TARGET_CLASS作用域代理,解决了单例Bean注入短作用域Bean的类型兼容问题,但WebServiceConfig是默认单例的配置类,内部创建webServiceTemplate的@Bean方法会在Spring容器启动阶段就执行,此时没有活跃的HTTP请求,代理无法获取到真实的Security实例,因此触发Scope 'request' is not active异常。

解决方案

方案1:调整Security的调用时机(推荐)

不要在webServiceTemplate的初始化阶段访问Security的属性,改为请求处理阶段动态获取:

  1. 新增Spring上下文工具类,用于手动获取Bean:
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return context.getBean(clazz);
    }
}
  1. 给WebServiceTemplate添加拦截器,在请求执行时再获取Security实例填充参数:
@Configuration
public class WebServiceConfig {
    // 移除Security的直接注入
    @Bean
    public WebServiceTemplate webServiceTemplate() {
        WebServiceTemplate template = new WebServiceTemplate();
        template.setInterceptors(new ClientInterceptor[]{securityParamInterceptor()});
        // 其他基础配置
        return template;
    }

    @Bean
    public ClientInterceptor securityParamInterceptor() {
        return new ClientInterceptor() {
            @Override
            public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
                // 此时处于请求处理阶段,request作用域活跃,可以正常获取Security实例
                Security security = ApplicationContextProvider.getBean(Security.class);
                // 从security中取出参数,写入webservice请求头/报文即可
                return true;
            }
            // 剩余接口方法默认实现省略
        };
    }
}

方案2:使用ObjectProvider延迟注入

如果要保留在WebServiceConfig中注入Security的逻辑,可以用ObjectProvider包装避免初始化阶段触发实例化:

@Configuration
public class WebServiceConfig {
    @Autowired
    private ObjectProvider<Security> securityProvider;

    @Bean
    public WebServiceTemplate webServiceTemplate() {
        WebServiceTemplate template = new WebServiceTemplate();
        // 注意:此处不能调用securityProvider.getObject(),必须等到请求处理阶段再调用获取实例
        return template;
    }
}

方案3:调整Security的作用域(仅业务允许时使用)

如果Security中存储的不是请求级别的独有信息,可以将它的作用域调整为单例/会话作用域,从根源避免作用域不匹配问题:

// 示例改为单例,去掉request作用域配置
@Service
@EnableConfigurationProperties(SecurityProperties.class)
public class Security {
    // 原有逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:15:03