XML配置的Java配置类似物不起作用

问题描述 投票:0回答:1

TL / DR:问题归结为创建自定义Spring范围,将具有prototype的作用域的bean注入到带有proxyMode = ScopedProxyMode.TARGET_CLASS的单例中,但是仍然在配置的Java配置版本中获得了一个单例(尽管它可以正常工作使用XML也可以)。

UPDATE:问题已解决,请参见答案。


我正在使用jBehave为我们的Spring应用程序编写BDD测试方案。最近,我们认为在执行测试方案时需要独立性(这意味着必须在每个方案之前重置测试上下文),并在网上找到this文章,确切地解决了我们正在处理的问题。

本文建议创建一个自定义Spring Scenario范围,将其分配给表示测试上下文的类,并注入AOP代理而不是上下文文件。

我已经按照文章进行了编码,并且效果很好,但是我们需要的是Java配置而不是XML,当我将所有更改都转换为Java配置时,它就停止了工作-这意味着在每个测试方案之后,Map中的StoryContext未重置,并且包含先前方案中的值。

我的更改如下:

  • ScenarioScope注释标记@Component类:
@Component
public class ScenarioScope implements Scope {

    private final ConcurrentMap<String, Object> cache = new ConcurrentHashMap<>();

    @BeforeScenario
    public void startScenario() {
        cache.clear();
    }

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        return cache.putIfAbsent(name, objectFactory.getObject());
    }

    @Override
    public Object remove(String name) {
        return cache.remove(name);
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {
    }

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

    @Override
    public String getConversationId() {
        return "scenario scope";
    }
}
  • 创建了一个Spring配置类以添加新的作用域:
@Configuration
public class SpringConfiguration {

    @Bean
    public static CustomScopeConfigurer scopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("scenario", new ScenarioScope());
        return configurer;
    }
}
  • StoryContext@Component注释注释@Scope类:
@Component
@Scope(value = "scenario", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class StoryContext {

  private Map<String, Object> storyContext = new HashMap<>();

  public void put(String key, Object value) {
    storyContext.put(key,value);
  }

  public <T> T get(String key, Class<T> tClass) {
    return (T) storyContext.get(key);
  }

  @PostConstruct
  public void clearContext() {
    storyContext.clear();
  }
}

据我所知,上面的代码类似于XML配置,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation=" http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config />
    <context:component-scan base-package="foo"/>

    <bean id="scenarioScope" class="foo.ScenarioScope"/>

    <bean class="foo.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="scenario" value-ref="scenarioScope"/>
            </map>
        </property>
    </bean>

    <bean id="storyContext" class="foo.StoryContext" scope="scenario">
        <aop:scoped-proxy/>
    </bean>
</beans>

任何人都可以指出我为什么Java配置无法按预期工作吗?我花了一些时间研究stackoverflow,但是大多数类似的问题都是通过在proxyMode = ScopedProxyMode.TARGET_CLASS批注中添加@Scope来解决的。]

UPDATE:

因此,我尝试通过注释/分解文件中的相应行,逐步将XML从Java配置转移到Java配置,并发现问题出在代码的这一部分:
    <bean class="foo.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="scenario" value-ref="scenarioScope"/>
            </map>
        </property>
    </bean>

当我替换为]时>

@Configuration
public class SpringConfiguration {

    @Bean
    public static CustomScopeConfigurer scopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("scenario", new ScenarioScope());
        return configurer;
    }
}

StoryContext bean成为单例。我尝试通过注册自定义BeanFactoryPostProcessor并按照registerScope()所述使用here方法来做另一种方式,但它也没有用。

TL / DR:问题归结为创建自定义Spring范围,使用proxyMode = ScopedProxyMode.TARGET_CLASS将类似原型的范围内的bean注入到一个单例中,但仍然在...

java spring spring-aop jbehave dynamic-proxy
1个回答
0
投票

我设法解决了这个问题,解决方案很简单:ScenarioScope类中的SpringConfiguration实例必须由Spring容器管理,而不是通过new()运算符创建:

@Configuration
public class SpringConfiguration {

    @Bean
    public static CustomScopeConfigurer scopeConfigurer(ScenarioScope scenarioScope) {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        configurer.addScope("scenario", scenarioScope);
        return configurer;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.