Dan*_*Dan 6 grails spring multi-tenant
我希望能够根据用户在运行时所属的租户选择特定的Spring(或Grails)上下文配置.假设我使用Spring Security并在登录期间检索tenantId.想象一下,现在我有两个租户,他们支付不同的佣金.如何在没有太多管道的情况下将特定服务注入控制器?这是两个不同的背景.所以,我应该根据租户注入不同的ExchangeService.
@Configuration
public class FooTenant{
@Bean
public ExchangeService bar() {
return new ZeroCommisionExchangeService ();
}
}
@Configuration
public class BarTenant{
@Bean
public ExchangeService bar() {
return new StandardCommisionExchangeService ();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我知道我可以获得对Spring上下文的引用并"手动"请求服务,但我正在寻找一个更通用的解决方案,其中这个问题由IoC框架解决.
几年前,我们需要这样的东西,但仅适用于DataSource
s 和ViewResolvers
。我们使用 spring 的TargetSource
解决方案开发了一个解决方案。(最初我们使用了 a,HotswappableTargetSource
但这不足以满足我们的用例。
我们开发的代码可以在多租户目录中找到。
它是完全可配置且灵活的。
基本上你要做的就是配置 aContextSwappableTargetSource
并告诉它需要返回什么类型的接口/类。
<bean id="yourTentantBasedServiceId" class="biz.deinum.multitenant.aop.target.ContextSwappableTargetSource">
<constructor-arg value="ExchangeService" />
</bean>
Run Code Online (Sandbox Code Playgroud)
默认情况下是根据tenantId 在ApplicationContext 中查找bean(请参阅 参考资料BeanFactoryTargetRegistry
)。但是,您可以指定其中的一个或多个(我们使用JndiLookupTargetRegistry
动态查找数据源,它允许动态添加租户而无需重新启动应用程序)。
如果您显式配置 a,BeanFactoryTargetRegistry
则可以添加 aprefix
和suffix
。
<bean id="exchangeService" class="biz.deinum.multitenant.aop.target.ContextSwappableTargetSource">
<constructor-arg value="ExchangeService" />
<property name="targetRegistry>
<bean class="biz.deinum.multitenant.aop.target.registry.impl.BeanFactoryTargetRegistry">
<property suffix="ExchangeService"/>
</bean>
</property>
</bean>
Run Code Online (Sandbox Code Playgroud)
fooExchangeService
现在,对于 foo ,它将查找名为bar 的bean barExchangeService
。
tenantId 存储在ThreadLocal
包装在ContextHolder
. 您需要找到一种方法来填充和清除本地线程(通常 servletFilter
会执行此操作。
在您的代码中,您现在可以简单地使用该接口ExchangeService
,并在运行时根据tenantId
正确的实现进行查找。
另请参阅http://mdeinum.wordpress.com/2007/01/05/one-application-per-client-database/
归档时间: |
|
查看次数: |
1780 次 |
最近记录: |