3

当我们使用自定义弹簧范围 - “租户”时,我们正在拥有一个产品。它与我们的系统架构密切相关。

在产品上线期间,我们决定放弃这个范围,但我们真的不想破坏向后兼容性。换句话说,我们希望现有的产品实现在没有错误的情况下启动,例如:

bean初始化失败;嵌套异常是 java.lang.IllegalStateException: No Scope registered for scope 'tenant'

我们也不想更正 spring 配置或任何 java 类( @Scope("tenant")发生的地方)中出现的任何租户定义。

我们在使用自定义加载 bean 定义时设法忽略了范围

XmlBeanDefinitionReader

似乎我们缺少过滤任何 bean 创建(任何 BeanDefinition )并忽略范围的一般概念 - 用 Singleton 替换它。

这是代码

这是覆盖范围的代码:

 
new ReaderEventListener()
            {

@Override public void importProcessed(final ImportDefinition importDefinition) { // } @Override public void defaultsRegistered(final DefaultsDefinition defaultsDefinition) { // } @Override public void componentRegistered(final ComponentDefinition componentDefinition) { for (final BeanDefinition beanDefinition : componentDefinition.getBeanDefinitions()) { if ("tenant".equalsIgnoreCase(beanDefinition.getScope())) { beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); if (LOG.isDebugEnabled()) { LOG.debug("Adjusting bean defintion for " + beanDefinition + " - ignoring tenant scope - please modify it manually to avoid confussion."); } } } for (final BeanDefinition beanDefinition : componentDefinition.getInnerBeanDefinitions()) { if ("tenant".equalsIgnoreCase(beanDefinition.getScope())) { beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON); if (LOG.isDebugEnabled()) { LOG.debug("Adjusting bean defintion for " + beanDefinition + " - ignoring tenant scope - please modify it manually to avoid confussion."); } } } } @Override public void aliasRegistered(final AliasDefinition aliasDefinition) { // } }); <code>

看起来它在大多数情况下都在工作,除了这样的情况:EXACT REGEX STARTS_WITH ENDS_WITH CONTAINS 看起来它能够更改包装的范围租户

org.springframework.beans.factory.config.ListFactoryBean

但不适用于底层的豆类....

值得一提的是,我们自己一个一个地加载包含 bean 定义的文件。

4

1 回答 1

1

您可以注册租户范围并将其实现为单例吗?

public class TenantScopeMock implements Scope {
  @Autowired private ApplicationContext appContext;

  public Object get(final String name, final ObjectFactory objectFactory) {
    if (!appContext.containsBean(name))
      ((SingletonBeanRegistry)appContext.getBeanFactory()).registerSingleton(name, objectFactory.getObject());
    return appContext.getBean(name);
  }

  public String getConversationId() {
    return null;
  }

  public void registerDestructionCallback(final String theName, final Runnable callback) {
  }

  public Object resolveContextualObject(String key) {
    return null;
  }

  public Object remove(final String theName) {
    return null;
  }

}

并注册:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
  <property name="scopes">
    <map>
      <entry key="tenant">
        <bean class="mypackage.TenantScopeMock" />
      </entry>
    </map>
  </property>
</bean>
于 2012-10-31T11:09:49.133 回答