使用 Google Guice 注入 java 属性

2022-09-02 13:20:46

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

Property1=TEST
Property2=25

package 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. 是否有其他方法使属性在所有类中都可用?

答案 1

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

不,通过这样做,你违背了依赖关系注入模式的目的,并且还把所有实现都耦合到Guice。您的实现根本不应与 guice 交互,除非通过(现在是标准化的)注释。

实例化一个新的注射器,如

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

在所有嵌套类中?

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

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

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

这些属性的注入方式与 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

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

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