5

我的 Spring Java 配置中有这个 bean:

@Bean
@Scope( proxyMode=ScopedProxyMode.TARGET_CLASS, value=SpringScopes.DESKTOP )
public BirtSession birtSession() {
    return new BirtSession();
}

对于测试,我需要一个没有范围的模拟(测试中没有“桌面”范围)。但是当我为我的测试创建一个配置时,它会导入上述配置并包含:

@Bean
public BirtSession birtSession() {
    return new MockSession();
}

我得到了一个“桌面”范围的模拟 bean :-(

如何让 Spring“忘记”@Scope注释?

PS:当我不使用@Import和使用复制和粘贴但我不想这样做时它可以工作。

4

2 回答 2

1

问题似乎ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod()在于使用ScopedProxyCreator.createScopedProxy()静态方法来创建作用域 bean 定义:

// replace the original bean definition with the target one, if necessary
        BeanDefinition beanDefToRegister = beanDef;
        if (proxyMode != ScopedProxyMode.NO) {
            BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
                    new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS);
            beanDefToRegister = proxyDef.getBeanDefinition();
    }

由于BeanDefinitionHolder返回 aRootBeanDefinition而不是ConfiguratioClassBeanDenition作用域代理 bean 定义(即ScopedProxyFactoryBean)不能被另一个 Java 配置类覆盖。

一种解决方法可能是在 xml 配置文件中声明要覆盖的范围 bean 并将其导入@ImportResource.

于 2013-02-05T17:10:56.043 回答
0

问题不在于 Spring 保留注释,问题在于 Spring 首先尝试解析“生产性”配置,为了做到这一点,它检查范围是否可用。Spring 急切地检查范围。所以它永远不会到达第二个/覆盖 bean 定义。

创建一个虚拟范围:

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;

public class MockSpringScope implements org.springframework.beans.factory.config.Scope {

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

    @Override
    public Object get( String name, ObjectFactory<?> objectFactory ) {
        Object result = objects.get( name );
        if( null == result ) {
            result = objectFactory.getObject();
            objects.put( name, result );
        }
        return result;
    }

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

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

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

    @Override
    public String getConversationId() {
        // NOP
        return null;
    }

}

并将其注册为“桌面”范围。这将 Spring 允许成功解析生产配置。

于 2013-02-05T08:27:53.510 回答