我正在尝试通过Spring的ThreadLocalTargetsource
实现一个ThreadLocal变量,下面是一个在线示例(并尽我所能):
open class TenantStore(var tenantId: String? = null) {
fun clear() {
this.tenantId = null
}
}
@Configuration
internal class TenancyConfiguration {
@Bean(name = ["tenantThreadLocal"],destroyMethod = "destroy")
fun threadLocalTenantStore() = ThreadLocalTargetsource().apply {
targetBeanName = "tenantStoreImpl"
}
@Primary
@Bean(name = ["proxiedThreadLocalTargetsource"])
fun proxiedThreadLocalTargetsource(threadLocalTargetsource: ThreadLocalTargetsource) = ProxyFactoryBean().apply {
targetsource = threadLocalTargetsource
}
@Bean(name = ["tenantStoreImpl"])
@Scope(scopeName = SCOPE_PROTOTYPE)
fun protoTenantStore(): TenantStore = TenantStore()
}
这由2个组件(单个),一个过滤器和一个普通bean消耗。
@Component
class TenantFilter(private val tenantStore: TenantStore) : Filter {
override fun doFilter(servletRequest: ServletRequest,servletResponse: ServletResponse,filterChain: FilterChain) {
// ...
tenantStore.tenantId = tenantHeader
filterChain.doFilter(servletRequest,servletResponse)
}
@Component
class OtherComponent(private val tenantStore: TenantStore) {
fun doSomething(){
println("tenant id: ${tenantStore.tenantId}")
}
}
- 在过滤器中,我正确获取了CGLIB代理
- 但是在其他组件中我没有。 Spring在单例中注入一个新实例(由于
prototype
范围),仅此而已,线程之间始终是同一实例。
然后
- 我无法使用
request
范围,因为每个线程都需要它。 -
thread
范围是一个选项,但是我失去了ThreadLocal的弹簧处理能力,我不需要完整的范围,只需这个简单的结构(TenantStore)。
我正在寻找任何类似的实现或技巧,以使它依赖于ThreadLocal变量的所有组件都可以透明地工作。