设置某个配置文件时不加载Spring bean

Zer*_*One 10 java spring spring-profiles spring-bean

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

public interface ExternalService {
// ...
}

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

@Service
@Primary
@Profile({"stub"})
public class StubExternalService implements ExternalService {
// ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Zer*_*One 16

事实证明答案非常简单:!在配置文件名称前面添加一个not-operator():

@Service
@Primary
@Profile({"!stub"})
public class ExternalServiceImpl implements ExternalService {
// ...
}
Run Code Online (Sandbox Code Playgroud)

这样,只有在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).