12

在使用 Spring DI applicationContext.xml 声明依赖注入方式的经验后,我现在尝试弄清楚如何对 Java EE6 CDI 做同样的事情。

使用 Spring,我可以使用多个配置文件(如 unittest.xml、devel.xml、qa.xml、production.xml)发布我的 .jar,并使用命令行参数或环境变量激活它们。

使用 CDI,我可以在beans.xml中使用 @Alternative 并在web.xml中使用属性,但似乎无法为不同的环境提供多个 beans.xml。

我不想使用 Maven 配置文件/过滤器来生成我的应用程序的 4-6 个版本,尽管我知道对于某些情况下这将是更好的解决方案(即向客户发送准备好的构建战争 - 但我只在内部使用我的战争所以让我们节省编译时间!)

最好,我还可以从文件系统加载这些配置文件,以便系统管理员可以编辑它们,而无需重新构建应用程序。

拥有多个依赖项和属性配置集的 Java EE6 方式是什么?

如果没有,截至 2013 年推荐的替代方案是什么?使用弹簧?接缝?古斯?我看到了 Apache DeltaSpike 的提及,但从网页来看,它们似乎仍然是 alpha。

4

3 回答 3

12

我会使用动态生产者,使用 aQualifier来确定所需的环境

// 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; }
     }

}

所以这里容器将所有可用的Greeting实现注入到GreetingFactory中,这反过来又作为@Producer预期的实现,基于系统属性“deployenv”的决定。

于 2013-06-04T15:00:24.877 回答
2

Carlo 的上述回答很好,我们在 DeltaSpike和 ProjectStage中拥有所有这些。值得一看,这样你就不必自己写了。

于 2013-06-04T15:39:58.510 回答
1

M.-Leander Reimer 在他的演讲Migrating a JSF-Based Web Application from Spring 3 to Java EE 7 and CDI (Slide 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();
    }
 }

他使用一个@ProfileAlternative模仿 Spring 的自定义注释@Profile和一个 CDI 扩展来观察ProcessAnnotatedType事件到veto()类型,如果它使用配置文件进行注释并且配置文件不活动。

于 2015-07-03T15:37:20.907 回答