Spring默认使用配置文件进行装配与Profile相关

7
我有两个豆子,都实现了邮件功能。其中一个只能在应用服务器上部署时才能使用,另一个则用于测试。
我们为每个开发者和环境设置了配置文件。我想在实际进行测试时仅连接测试豆子。当不进行测试时应该使用另一个豆子。如何实现这一点?
@Component
@Profile("localtest")
public class OfflineMail implements Mailing {}

解决方案:
使用“默认值”,我在某个地方看到过,但对于像“dev”这样的配置文件似乎没有回退到“默认值”。
@Component
@Profile("default")
public class OnlineMail implements Mailing {}

-> 找不到需要注入的bean异常。

不指定配置文件:

@Component
public class OnlineMail implements Mailing {}

-> 运行“localtest”配置文件时会抛出唯一的异常。

添加所有配置文件:

@Component
@Profile("prod")
@Profile("integration")
@Profile("test")
@Profile("dev1")
@Profile("dev2")
@Profile("dev3")
...
public class OnlineMail implements Mailing {}

这实际上是有效的,但我们的开发人员没有编号,他们使用“dev<WindowsLogin>”,添加配置文件可能适用于一个bean,但如果将其用于多个bean,则会遇到麻烦,因为这肯定会变得很丑陋。

使用类似于@Profile(“!localtest”)的东西似乎也不起作用。

有没有人知道更好的方法来获得“默认情况下进行连接,如果没有找到特定的bean”?


如果没有使用@Profile@Component必须是默认的bean,如果没有进行任何装配。您是否尝试通过为组件设置名称来避免唯一异常?我的意思是,有@Profile("localtest")和没有它的@Component("mail") - n1ckolas
3个回答

10

我终于找到了一个简单的解决方案。

在线邮件默认情况下只是出现问题了。

@Component
public class OnlineMail implements Mailing {}

使用@Primary注解,离线邮件优先于在线邮件,并避免了唯一异常。

@Component
@Profile("localtest")
@Primary
public class OfflineMail implements Mailing {}

2

试试这个:

@Component
@Profile("production")
public class OnlineMail implements Mailing {}

@Component
@Profile("localtest")
public class OfflineMail implements Mailing {}

使用@ActiveProfiles("localtest")运行测试,并将生产环境的默认配置文件设置为"production"。

另外,我希望在Spring的下一个版本中引入ActiveProfilesResolver,详情请参考SPR-10338 - 这可能会对您有所帮助(避免使用"dev1"、"dev2"等名称)。


我不理解这个解决方案的重点。我们在部署应用程序的任何地方都设置了正确的环境,所以Spring不应该加载默认值,对吧?而且我不确定如何将测试的默认值与生产资源分开,因为我们的测试文件中也会有生产资源。 - Udo Held
有两种类型的配置文件 - 默认配置文件和活动配置文件,请查看https://dev59.com/3mkw5IYBdhLWcg3wPIB7。 - Michail Nikolaev
因此,最好避免为已经有模拟的任何bean使用默认(空)Spring配置文件 - 使用“production”和“localtest”配置文件。在启动时,使用@ActiveProfiles进行测试并使用'pring.profiles.default'或'pring.profiles.active'进行服务器选择所需配置文件。 - Michail Nikolaev
找到了更好的解决方案。 "默认"行为可以直接使用,而测试行为则使用@Primary来获取优先级。感谢您提供的想法。我已经在测试中使用了@ActiveProfiles - Udo Held

0

Spring非常好地支持了通过@Profile注入Bean:

interface Talkative {
    String talk();
}

@Component
@Profile("dev")
class Cat implements Talkative {
        public String talk() {
        return "Meow.";
    }
}

@Component
@Profile("prod")
class Dog implements Talkative {
    public String talk() {
        return "Woof!";
    }
}

在单元测试中工作正常

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContex-test.xml"})
@ActiveProfiles(value = "dev")
public class InjectByDevProfileTest
{
    @Autowired
    Talkative talkative;

    @Test
    public void TestTalkative() {
        String result = talkative.talk();
        Assert.assertEquals("Meow.", result);

    }
}

在Main()中工作:

@Component public class Main {

        public static void main(String[] args) {
            // Enable a "dev" profile
            System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("applicationContext.xml");
            Main p = context.getBean(Main.class);
            p.start(args);
        }

        @Autowired
        private Talkative talkative;

        private void start(String[] args) {
            System.out.println(talkative.talk());
        }
    }

请查看演示代码:https://github.com/m2land/InjectByProfile


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接