Java 在一场战争中有多个CDI配置文件(devel、beta、qa、production)?
有了使用SpringDI applicationContext.xml声明依赖注入的经验,我现在试图找出如何使用JavaEE6CDI实现同样的功能 使用Spring,我可以将.jar与几个配置文件一起提供,如 并使用命令行参数或环境变量激活它们 有了CDI,我可以在beans.xml中使用@Alternative,在web.xml中使用properties,但似乎没有办法为不同的环境提供多个beans.xml 我不想使用Maven配置文件/过滤器来生成我的应用程序的4-6个版本,尽管我知道在某些情况下,这将是更好的解决方案(即向客户提供现成的构建战争-但我只在内部使用我的战争,所以让我们节省编译时间!) 最好,我还能够从文件系统加载这些配置文件,这样系统管理员就可以编辑它们,而无需重新构建应用程序 JavaEE6拥有多个依赖项和属性配置集的方式是什么Java 在一场战争中有多个CDI配置文件(devel、beta、qa、production)?,java,spring,java-ee-6,cdi,Java,Spring,Java Ee 6,Cdi,有了使用SpringDI applicationContext.xml声明依赖注入的经验,我现在试图找出如何使用JavaEE6CDI实现同样的功能 使用Spring,我可以将.jar与几个配置文件一起提供,如 并使用命令行参数或环境变量激活它们 有了CDI,我可以在beans.xml中使用@Alternative,在web.xml中使用properties,但似乎没有办法为不同的环境提供多个beans.xml 我不想使用Maven配置文件/过滤器来生成我的应用程序的4-6个版本,尽管我知道在某些
如果没有,截至2013年,推荐的替代方案是什么?使用弹簧?接缝Guice?我看到有人提到ApacheDeltaspike,但从网页上看,它们仍然像是alpha juding。我会使用动态生产者,使用
限定符来识别所需的环境
// The qualifier for the production/qa/unit test
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD,
ElementType.FIELD, ElementType.PARAMETER})
public @interface Stage {
String value() default "production";
}
// The interface for the stage-dependant service
public interface Greeting{
public String sayHello();
}
// The production service
@Stage("production")
public class ProductionGreeting implements Greeting{
public String sayHello(){return "Hello customer"; }
}
// The QA service
@Stage("qa")
public class QAGreeting implements Greeting{
public String sayHello(){return "Hello tester"; }
}
// The common code wich uses the service
@Stateless
public class Salutation{
@Inject Greeting greeting;
public String sayHello(){ return greeting.sayHello(); };
}
// The dynamic producer
public class GreetingFactory{
@Inject
@Any
Instance<Greeting> greetings;
public String getEnvironment(){
return System.getProperty("deployenv");
}
@Produces
public Greeting getGreeting(){
Instance<Greeting> found=greetings.select(
new StageQualifier(getEnvironment()));
if (!found.isUnsatisfied() && !found.isAmbiguous()){
return found.get();
}
throw new RuntimeException("Error ...");
}
public static class StageQualifier
extends AnnotationLiteral<Stage>
implements Stage {
private String value;
public StageQualifier(String value){
this.value=value;
}
public String value() { return value; }
}
}
//生产/质量保证/单元测试的限定符
@限定词
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.TYPE,ElementType.METHOD,
ElementType.FIELD,ElementType.PARAMETER})
公共@接口阶段{
字符串值()默认为“生产”;
}
//阶段相关服务的接口
公共界面问候语{
公共字符串sayHello();
}
//生产服务
@舞台(“制作”)
公共类ProductionGreeting实现问候语{
公共字符串sayHello(){返回“Hello customer”;}
}
//质量保证服务
@阶段(“qa”)
公共类实现问候语{
公共字符串sayHello(){返回“Hello tester”;}
}
//使用该服务的公共代码
@无国籍
公开课敬礼{
@注入问候语;
公共字符串sayHello(){return greeting.sayHello();};
}
//动态生产者
公共类迎宾工厂{
@注入
@任何
实例问候;
公共字符串getEnvironment(){
returnsystem.getProperty(“deployenv”);
}
@产生
公共问候语{
找到实例=问候语。选择(
新的stageequalifier(getEnvironment());
如果(!found.isUnsatisfied()&&!found.isAmbiguous()){
返回find.get();
}
抛出新的运行时异常(“错误…”);
}
公共静态类均衡器
扩展AnnotationLiteral
实施阶段{
私有字符串值;
公共分段均衡器(字符串值){
这个。值=值;
}
公共字符串值(){return value;}
}
}
因此,在这里,容器将所有可用的问候语
实现注入问候工厂
,该工厂反过来充当目标工厂的@Producer
,根据系统属性“deployenv”的决定。Carlo的上述答案很好,我们在DeltaSpike中有所有这些。值得一看,这样你就不必自己写了。M.-Leander Reimer在他的演示文稿(幻灯片32)中建议了一种替代解决方案,使用CDI扩展:
@Alternative
@Stereotype
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ProfileAlternative {
Profile[] value();
}
public void processAnnotated(@Observes ProcessAnnotatedType<?> event) {
ProfileAlternative pa = getProfileAlternative(event);
if (profileAlternativeIsNotActive(pa)) {
event.veto();
}
}
@备选方案
@刻板印象
@目标({ElementType.TYPE,ElementType.METHOD})
@保留(RetentionPolicy.RUNTIME)
public@interface profiler可选{
配置文件[]值();
}
public void processAnnotated(@ProcessAnnotatedType事件){
ProfileAlternative pa=getProfileAlternative(事件);
如果(可选配置文件不活动(pa)){
事件否决权();
}
}
他使用一个自定义注释@ProfileAlternative
模仿Spring的@Profile
,并使用一个CDI扩展来观察ProcessAnnotatedType
事件,以否决()
该类型,前提是该类型使用了一个配置文件进行注释,并且该配置文件未处于活动状态。我建议不要给系统管理员更改一切的能力。让他们更改选定的子集。好啊但并不是所有的东西,否则有一天你会花很长时间调试他们犯下的错误,你无法重现。谢谢你的示例源代码。对于@products来说,这是一个有趣的例子,似乎我必须为存在于多个变体中的每个类编写一个工厂,可能只有几个。如果我有一个dozend“@injectstringpassword”变量,它也会变得混乱,因为我必须使用限定符来区分几种字符串类型。因此,它似乎无法扩展到大型应用程序,或者?嗯,这是为类型安全性付出的代价。。。此外,@Stage
限定符可以用于所有可配置类型,同样可以用于可以生成所有动态注入bean的GreetingFactory
。对于@Inject-String-password
,您可以引入一个限定符,在@Inject-Config(“db.password”)String-password
中定义origin属性。另一种(更激进的)方法是利用可移植扩展API。如何在代码中的各个阶段之间切换?换句话说,stage在哪里定义/配置,maven构建需要更改什么文件?在上面的代码中,它是在GreetingFactory
中通过方法getEnvironment()
完成的。在示例中,它是一个简单的系统属性,但在方法中,您可以加载属性文件。@Exclude(exceptIf=Development.class)@替代方法看起来很有希望,但不同的项目阶段通常使用相同的类,但具有不同的属性(用户名/密码),它们将如何被注入?文档中只显示“待办事项”: