自定义Spring @Scope实现多租户Bean隔离时实例不切换问题咨询
问题原因及解决方案
1. 自定义Scope未向Spring容器注册
你仅实现了TenantScope类,Spring默认无法识别tenant这个自定义作用域,需要主动完成注册:
@Configuration public class ScopeConfig { @Bean public CustomScopeConfigurer tenantScopeConfigurer() { CustomScopeConfigurer configurer = new CustomScopeConfigurer(); configurer.addScope("tenant", new TenantScope()); return configurer; } }
2. @Scope未设置正确的代理模式
@Scope默认的代理模式是ScopedProxyMode.DEFAULT(等同于无代理),如果你的some_API Bean被注入到单例Bean中,Spring启动时只会初始化一次实例,后续调用永远返回该对象。需要指定代理模式让Spring每次调用都从当前Scope中获取真实实例:
@Scope(scopeName = "tenant", proxyMode = ScopedProxyMode.TARGET_CLASS) @Bean public SomeAPI someAPI() { /* Load tenant credentials.. */ return new SomeAPI(credentials); }
注:如果
SomeAPI是接口实现类,也可以用ScopedProxyMode.INTERFACES减少代理开销。
3. TenantScope的get()方法实现错误
你注释省略了get()方法的实现,若逻辑错误也会导致始终返回同一个对象,正确实现参考:
@Override public Object get(String name, ObjectFactory<?> objectFactory) { String tenantId = getConversationId(); if (tenantId == null) { throw new IllegalStateException("当前无租户上下文"); } String scopeKey = tenantId + ":" + name; scopedObjects.computeIfAbsent(scopeKey, k -> objectFactory.getObject()); return scopedObjects.get(scopeKey); }
注意:存储key需要同时拼接租户ID和Bean名称,避免同租户下不同Bean的实例冲突。
4. 测试代码注入方式错误
如果你的测试代码中是直接@Autowired注入的some_API实例,没有设置代理模式的前提下,注入的就是首次初始化的固定实例,不会随租户上下文切换而变化,配置代理模式后即可解决。
内容的提问来源于stack exchange,提问作者Kanghu
相关产品推荐
相关产品推荐

