13

背景:所以,我有几个连接外部系统的 bean。对于开发来说,模拟外部系统并用一些产生或多或少静态响应的实现替换接口 bean 是很方便的。所以我一直在做的是创建一个接口,真正的实现和一个像这样的存根实现:

public interface ExternalService {
// ...
}

@Service
public class ExternalServiceImpl implements ExternalService {
// ...
}

@Service
@Primary
@Profile({"stub"})
public class StubExternalService implements ExternalService {
// ...
}

...这很好用:如果存根配置文件不存在,则根本不会加载存根 bean。如果它存在,由于 @Primary 注释,它很好地取代了真正的实现。

问题:然而,现在我第一次在这样的情况下运行,我实际上已经获得了同一接口的两个实际实现。其中一个被定义为主要的,但另一个也可以通过从应用程序上下文中加载来使用。

我仍然想创建一个存根服务来替换它们,但是这次我将存根定义为@Primary 的旧方法不起作用,因为已经有一个主要实现。基本上我需要的是一种在设置存根配置文件时不加载主 bean 的方法,但我不知道如何做到这一点。网络搜索或其他 Stack Overflow 问题似乎没有帮助。

4

1 回答 1

24

!事实证明,答案非常简单:在配置文件名称前添加一个非运算符 ( ):

@Service
@Primary
@Profile({"!stub"})
public class ExternalServiceImpl implements ExternalService {
// ...
}

stub这样,只有在-profile 不活动时才加载 bean 。在Spring 3.2 M1中添加了对这个特性的支持。

但是有一个警告:如果你写@Profile({"!stub", "foo"}),逗号被视为“或”,而不是“和”。stub因此,如果未激活或激活,则此示例 bean 将被激活foo

编辑/添加: Spring 5.1 添加了对配置文件的新表达式语言的支持:!stub & foostub不活动和活动时foo激活。巨大的成功!如果你使用括号,你甚至可以混合和匹配 ands 和 ors: production & (us-east | eu-central)

于 2014-08-04T07:59:02.160 回答