Java CDI:如何使用具有多个值的限定符在运行时更改生成器?

时间:2015-08-10 22:02:20

标签: java dependency-injection cdi

我需要根据执行应用程序的环境(开发,测试,生产等)来更改JDBC连接的注入方式。 必须轻松处理新环境的添加。因此,考虑到佩莱格里尼对以下问题的解决方案,我试图实现这种行为:

Multiple CDI configuration profiles (devel, beta, qa, production) in one war?

但是,我的背景有点不同。我们来看看:

注射点是这样的:

@Inject 
private Connection conn;

我有两个连接工厂:

  1. ConnectionFactory :用于测试,验收和生产环境;
  2. ProxyConnectionFactory :仅适用于开发环境。
  3. 他们的定义如下:

    public inteface ConnectionFactory {
      public Connection getConnection();
    }
    
    @Environment({ "test", "acceptance", "production" })
    public CustomConnectionFactory implements ConnectionFactory {
      public Connection getConnection() {
        // Implementation code
      }
    }
    
    @Environment({ "development" })
    public ProxyCustomConnectionFactory implements ConnectionFactory {
      public Connection getConnection() {
        // Implementation code
      }
    }
    
    @Qualifier
    @Target({ TYPE, METHOD, PARAMETER, FIELD })
    @Retention(RUNTIME)
    @Documented
    public @interface Environment {
        String[] value() default {"production"};
    }
    

    最后,我的生产者代码使用以前的一个工厂为每个预期的环境生成适当的连接:

    public class ConnectionProducer {
    
      @Inject
      @Any
      Instance<ConnectionFacotry> connectionFactories;   
    
      public String getEnvironment(){
        return System.getProperty("deploy-environment");
      }
    
      @Produces
      public Connection produceConnection(){
    
        String[] profile = {getEnvironment().toLowerCase()};
    
        Instance<ConnectionFactory> found = connectionFactories.select(
          new EnvironmentQualifier(profile));
            if (!found.isUnsatisfied() && !found.isAmbiguous()){
              return found.get();
            }
            throw new RuntimeException("Error ...");
        }
    
        public static class EnvironmentQualifier 
          extends AnnotationLiteral<Environment> 
          implements Environment {      
          private String[] value;      
          public EnvironmentQualifier(String[] value) {
            this.value=value;      
          }             
          public String[] value() { return value; }
        }    
    
      }
    

    此代码引发运行时错误,因为指令found.isAmbiguous()的计算结果为true。我不确定,但我认为出现此问题是因为Environment限定符接受多个值。我做错了什么?

    我很感激任何建议。

2 个答案:

答案 0 :(得分:2)

我建议看看deltaspike project stage feature。这似乎是满足您需求的良好基础。

答案 1 :(得分:0)

我对你的代码不是很了解。但是,关于您的问题,您可以获得一个工厂,并在运行时根据指定的环境类型注入正确的依赖项。

例如,您的注释如下所示:

@Produces @Environment
public Connection getConnection(InjectionPoint ip) {
    Annotated annotated = ip.getAnnotated();
    Environment annotation = annotated.getAnnotation(Environment.class);
    EnvironmentType environment = annotation.environment();

    if(environment == EnvironmentType.DEVELOPMENT) {
        // return connection for development
    } else if(environment == EnvironmentType.TEST) {
        // return connection for production
    } else if(environment == EnvironmentType.ACCEPTANCE) {
        // return connection for acceptance
    } else {
        // return connection for production
    }
}

在您的生成器方法中,您可以获取要注入的bean的注释,提取所选环境并评估它:

{{1}}

如果我误解了,我很抱歉。

PD:请原谅我的英文