【问题标题】:Using Google Guice to inject java properties使用 Google Guice 注入 java 属性
【发布时间】:2012-04-04 01:54:09
【问题描述】:

我想使用 google guice 使属性在我的应用程序的所有类中都可用。我定义了一个模块,它加载和绑定属性文件 Test.properties

Property1=TEST
Property2=25

包 com.test;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

public class TestConfiguration extends AbstractModule {

    @Override
    protected void configure() {
    Properties properties = new Properties();
    try {
        properties.load(new FileReader("Test.properties"));
        Names.bindProperties(binder(), properties);
    } catch (FileNotFoundException e) {
        System.out.println("The configuration file Test.properties can not be found");
    } catch (IOException e) {
        System.out.println("I/O Exception during loading configuration");
    }

    }
}

我正在使用一个主类,我在其中创建了一个注入器来注入属性。

package com.test;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class Test {

    public static void main(String[] args) {
    TestConfiguration config = new TestConfiguration();
    Injector injector = Guice.createInjector(config);
    TestImpl test = injector.getInstance(TestImpl.class);
    }
}

package com.test;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class TestImpl {
    private final String property1;
    private final Integer property2;

        @Inject
        public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2) {

        System.out.println("Hello World");
        this.property1 = property1;
        this.property2 = property2;

        System.out.println(property1);
        System.out.println(property2);

        }
     }

现在我的问题。如果我的 TestImpl 创建了我也需要注入属性的其他类,并且这些类也需要注入属性,那么正确的方法是什么?

  1. 将注入器传递给所有子类,然后使用 injector.getInstance(...) 创建子类?

  2. 实例化一个新的注入器

    TestConfiguration config = new TestConfiguration();
    Injector injector = Guice.createInjector(config);
    TestImpl test = injector.getInstance(TestImpl.class);
    

在所有嵌套类中?

  1. 是否有其他方法可以使属性在所有类中可用?

【问题讨论】:

  • 您是否有理由手动更新它们,而不是使用 guice 将它们注入您的测试类(这将是正常的方式)?
  • 你的意思是为什么“TestConfiguration config = new TestConfiguration();”?你能举例说明如何以另一种方式做到这一点吗?
  • @markus: 不,不是TestConfiguration...new 模块是正常的。问题是关于TestImpl 创建您还需要注入属性的其他类。通常,您会将那些其他类(或其中的Providers)声明为TestImpl 的依赖项,因此Guice 可以创建它们,而不是您在TestImpl 中使用new 创建它们。
  • 我不清楚该怎么做。假设我要创建类 public class TestExtension { @Inject public TestExtension(@Named("Property1") String property1, @Named("Property2") Integer property2) { System.out.println(property1); System.out.println(property2); } } 我如何告诉 guice 创建它?
  • 您阅读过Getting Started 指南吗?这将告诉您如何使用 guice 以及如何设置简单的绑定。

标签: java properties guice


【解决方案1】:

将注入器传递给所有子类,然后使用 injector.getInstance(...) 创建子类?

不,这样做你违背了dependency injection 模式的目的,并将你的所有实现都耦合到了Guice。您的实现根本不应该与 guice 交互,除非通过(现在标准化的)注释。

实例化一个新的注入器

TestConfiguration config = new TestConfiguration(); 
Injector injector = Guice.createInjector(config); 
TestImpl test = injector.getInstance(TestImpl.class); 

在所有嵌套类中?

不,这更糟糕,因为您最终会得到多个注入器,因此多个上下文将阻止正确使用 scopes

理想情况下,您应该只在应用程序的引导过程中使用注入器。当然,引导它的方式很大程度上取决于应用程序。

是否有其他方法可以使所有属性都可用 上课?

可以像为 TestImpl 那样注入属性。 如果您希望 TestImpl 使用假设一个服务也需要一些属性(或其他服务),只需让 Guice 将其注入到 TestImpl。 Guice 负责所有的实例化/接线。只有当 Guice 自己无法解决这个问题时,您才应该使用活页夹告诉 Guice“如何进行”:

public class TestImpl {
    private final String property1;
    private final Integer property2;
    private final IService service;


        @Inject
        public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2, IService service) {
           this.property1 = property1;
           this.property2 = property2;
           this.service= service;
        }
    }
}

【讨论】:

    【解决方案2】:

    库“Governator”为 guice 注入提供了配置映射功能。方法不同,但可以从属性文件加载。

    https://github.com/Netflix/governator/wiki/Configuration-Mapping

    【讨论】:

      【解决方案3】:

      Guice configuration 库可以为您注入属性或 JSON 文件中的值到您的服务。

      您可以将文件 application.properties 注入到您的服务中:

      @BindConfig(value = "application", syntax = PROPERTIES)
      public class Service {
      
          @InjectConfig
          private int port;
      
          @InjectConfig
          private String url;
      
          @InjectConfig
          private Optional<Integer> timeout;
      }
      

      您必须简单地安装模块 ConfigurationModule

      public class GuiceModule extends AbstractModule {
          @Override
          protected void configure() {
              install(ConfigurationModule.create());
              requestInjection(Service.class);
          }
      }
      

      【讨论】:

        【解决方案4】:

        guice-config


        使用示例: 首先我们有一个属性文件'config.properties':

        test.key=test value
        

        我们想像这样注入这个值:

        @Inject
        @Config( Property.TEST_KEY )
        private String injectedValue;
        

        我们需要将 'config.properties' 文件的内容加载到 java.util.Properties 中并将其传递给 Config 模块:

        Properties props = new Properties();
        props.load(...);
        

        模块 configModule = new ConfigModule(props, Property.values() ); ...并注入:

        Injector injector = Guice.createInjector( configModule );
        TestClass testClass = injector.getInstance( TestClass.class );
        String injectedValue = testClass.getInjectedValue();
        

        注入的值将是“测试值”...

        【讨论】:

          【解决方案5】:

          “现在我的问题。如果我的 TestImpl 创建了其他类,我也需要注入属性,而这些类也需要注入属性,那么正确的方法是什么?”

          经验法则:避免使用“new” 除非绝对必要,否则不要让您的 Impl 类“创建其他类”。相反,告诉您的 TestImpl 当使用 guice 创建时,它应该注入所需的实例。

          【讨论】:

            猜你喜欢
            • 2017-05-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-09-22
            • 2017-07-14
            相关资源
            最近更新 更多