2012-05-31 78 views
4

我有一个类:吉斯注射

public class FizzBuzz { 
    @Named("Red") private String redService; 

    public static void main(String[] args) { 
     GuiceTest testApp = new GuiceTest(); 

     testApp.run(); 
    } 

    private void run() { 
     Injector inj = Guice.createInjector(new MyModule()); 

     redService = (String)inj.getInstance(String.class); 

     // Should print "red-service" but is instead an empty string! 
     System.out.println("redService = " + redService); 
    } 

    // ... Rest of class omitted for brevity 
} 

public class MyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(String.class).annotatedWith(Names.named("Red")).toInstance("red-service"); 
    } 
} 

在我的模块我指示吉斯绑定所有String.class实例@Named“红”字符串实例“红色服务”,但我在输出的打印语句中没有看到。我如何错误地使用Guice?

回答

18

让我总结出一些已经在这里提出的意见......

  1. 你忘了@Inject注释
  2. 我会强烈建议保持吉斯/注射器FizzFuzz之外。使用静态主要方法来引导您的应用程序(不是运行())。
  3. 将字符串绑定到常量可以通过bindConstant轻松完成。

THS给你带来的东西是这样的:

public class FizzFuzz { 
    @Inject 
    @Named("red") 
    private String service; 

    public static void main(String[] args) { 
     FizzFuzz fizzFuzz = Guice.createInjector(new AbstractModule() { 
      @Override 
      protected void configure() { 
       bindConstant().annotatedWith(Names.named("red")).to("red-service"); 
      }  
     }).getInstance(FizzFuzz.class); 

     System.out.println(fizzFuzz.service); 
    } 
} 
2

您忘记了@Inject之前@Named("Red")。 另外使用bindConstant()可以预见这种事情。

P.S.你为什么收到String而不是FizzBuzz

2

它应该是相当多用我的方式。
创建第一注记

@Retention(RetentionPolicy.RUNTIME) 
public @interface InjectSetting { 
    String value(); 
} 

创建吉斯模块

@Slf4j 
public class SettingModule extends AbstractModule { 
    private final Properties properties; 

    private SettingModule(Properties properties) { 
     this.properties = properties; 
    } 

    @Override 
    protected void configure() { 
     binder().bindListener(Matchers.any(), listener(((type, encounter) -> { 
      for (Field field : type.getRawType().getDeclaredFields()) { 
       if (field.isAnnotationPresent(InjectSetting.class)) { 
        field.setAccessible(true); 

        encounter.register(injector(instance -> { 
         try { 
          Object value = properties.get(
            field.getAnnotation(InjectSetting.class).value()); 

          field.set(instance, parse(value, field)); 
         } catch (IllegalAccessException e) { 
          binder().addError(e); 
         } 
        })); 
       } 
      } 
     }))); 
    } 

    TypeListener listener(BiConsumer<TypeLiteral<?>, TypeEncounter<?>> consumer) { 
     return consumer::accept; 
    } 

    MembersInjector<Object> injector(Consumer<Object> consumer) { 
     return consumer::accept; 
    } 

    Object parse(Object value, Field field) { 
     Type type = field.getType(); 

     if(type == boolean.class) 
      value = Boolean.parseBoolean(value.toString()); 
     else if(type == int.class) 
      value = Integer.parseInt(value.toString()); 

     return value; 
    } 

    public static Module of(String propertiesPath, String... more) { 
     Properties properties = new Properties(); 

     try { 
      properties.load(Files.newInputStream(Paths.get(propertiesPath, more))); 
     } catch(Exception e) { 
      log.error("can't load config file {}", propertiesPath); 
      throw new RuntimeException(e); 
     } 

     return new SettingModule(properties); 
    } 
} 

然后注入你的领域

@InjectSetting("database.port") 
private int port;