Dependency injection 如何在GoogleGuice中注入具有名称模式或正则表达式的属性列表?

Dependency injection 如何在GoogleGuice中注入具有名称模式或正则表达式的属性列表?,dependency-injection,binding,guice,Dependency Injection,Binding,Guice,使用Google Guice,我们可以从属性文件中注入如下内容: @Inject(optional = true) @Named("api.server.ip") private final String ip = "localhost"; api.server.ip.1=10.11.12.13 api.server.port.1=3000 api.server.path.1=/maps api.server.ip.2=10.11.12.14 api.server.port.2=3001 ap

使用Google Guice,我们可以从属性文件中注入如下内容:

@Inject(optional = true)
@Named("api.server.ip")
private final String ip = "localhost";
api.server.ip.1=10.11.12.13
api.server.port.1=3000
api.server.path.1=/maps
api.server.ip.2=10.11.12.14
api.server.port.2=3001
api.server.path.2=/phones
那么,如果我有这样一个属性文件:

@Inject(optional = true)
@Named("api.server.ip")
private final String ip = "localhost";
api.server.ip.1=10.11.12.13
api.server.port.1=3000
api.server.path.1=/maps
api.server.ip.2=10.11.12.14
api.server.port.2=3001
api.server.path.2=/phones

任务是应用程序需要访问多个服务器来调用请求,那么是否有任何方法可以使用GoogleGuice中的模式注入属性,或者有任何建议来解决此问题?谢谢你

Google Guice没有现成的解决方案,但您可以使用api做一些事情

下面是一段代码,它将注入由自定义属性注释注释的字段-

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.MembersInjector;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class PropertiesInjection {

    static class PropertiesModule extends AbstractModule {

        @Override
        protected void configure() {
            bindListener(Matchers.any(), new PropertiesTypeListener());
        }
    }

    static class PropertiesTypeListener implements TypeListener {

        public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
            Class<?> clazz = typeLiteral.getRawType();
            while (clazz != null) {
                for (Field field : clazz.getDeclaredFields()) {
                    if (field.getType() == String.class && field.isAnnotationPresent(Property.class)) {
                        Property annotation = field.getAnnotation(Property.class);
                        typeEncounter.register(new PropertyInjector<T>(field, annotation.value()));
                    }
                }
                clazz = clazz.getSuperclass();
            }
        }
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    @interface Property {
        String value();
    }

    static class PropertyInjector<T> implements MembersInjector<T> {

        private final Field field;
        private final String key;

        PropertyInjector(Field field, String key) {
            this.field = field;
            this.key = key;
        }

        @Override
        public void injectMembers(T instance) {
            try {
                field.set(instance, PropertiesFileDataProvider.getValue(key));
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    static class PropertiesFileDataProvider {

        private static final Map<String, String> PROPERTIES = new HashMap<>();

        static {
            PROPERTIES.put("api.server.ip", "localhost"); //load it from properties file. I am putting dummy values just for an example.
        }

        static String getValue(String key) {
            return PROPERTIES.getOrDefault(key, key);
        }
    }

    static class TestData {
        @Property("api.server.ip")
        private String property;
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new PropertiesModule());
        TestData instance = injector.getInstance(TestData.class);

        System.out.println(instance.property); //prints localhost
    }
}