How to bind String to variable in Guice?

别来无恙 提交于 2019-12-03 07:48:30

问题


I'm new to Guice and here is a naive question. I learned that we could bind String to a particular value through:

bind(String.class)
        .annotatedWith(Names.named("JDBC URL"))
        .toInstance("jdbc:mysql://localhost/pizza");

But what if I want to bind String to any possible characters?

Or I think it could be described this way:

How can I replace "new SomeClass(String strParameter)" with Guice?


回答1:


You first need to annotate the constructor for SomeClass:

class SomeClass {
  @Inject
  SomeClass(@Named("JDBC URL") String jdbcUrl) {
    this.jdbcUrl = jdbcUrl;
  }
}

I prefer to use custom annotations, like this:

class SomeClass {
  @Inject
  SomeClass(@JdbcUrl String jdbcUrl) {
    this.jdbcUrl = jdbcUrl;
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target({ElementType.FIELD, ElementType.PARAMETER})
  @BindingAnnotation
  public @interface JdbcUrl {}
}

Then you need to provide a binding in your Module:

public class SomeModule extends AbstractModule {
  private final String jdbcUrl; // set in constructor

  protected void configure() {
    bindConstant().annotatedWith(SomeClass.JdbcUrl.class).to(jdbcUrl);
  }
}

Then an time Guice creates SomeClass, it will inject the parameter. For instance, if SomeOtherClass depends on SomeClass:

class SomeOtherClass {
  @Inject
  SomeOtherClass(SomeClass someClass) {
    this.someClass = someClass;
  }

Often, when you think you want to inject a String, you want to inject an object. For instance, if the String is a URL, I often inject a URI with a binding annotation.

This all assumes there is some constant value you can define at module creation time for the String. If the value isn't available at module creation time, you can use AssistedInject.




回答2:


This might be off-topic, but Guice makes configuration much easier than writing an explicit binding for every String you need. You can just have a config file for them:

Properties configProps = Properties.load(getClass().getClassLoader().getResourceAsStream("myconfig.properties");
Names.bindProperties(binder(), configProps);

and voilà all your config is ready for injection:

@Provides // use this to have nice creation methods in modules
public Connection getDBConnection(@Named("dbConnection") String connectionStr,
                                  @Named("dbUser") String user,
                                  @Named("dbPw") String pw,) {
  return DriverManager.getConnection(connectionStr, user, pw);
}

Now just create your Java properties file myconfig.properties at the root of your classpath with

dbConnection = jdbc:mysql://localhost/test
dbUser = username
dbPw = password

or merge authorization information from some other source into the properties and you're set.




回答3:


I find a solution in the FAQ of Guice:

http://code.google.com/docreader/#p=google-guice&s=google-guice&t=FrequentlyAskedQuestions

In addition to define an annotation and a String attribute in MyModule, I need to write below line to get a instance of SomeClass:

SomeClass instance = Guice.createInjector(new MyModule("any string i like to use")).getInstance(SomeClass.class);

But I remembered that Injector.getInstance() should not be used except for the root object, so is there any better way to do this?




回答4:


I was able to inject a string through Named annotation.

@Provides
@Named("stage")
String stage() {
    return domain;
}

class SomeClass {
   @Inject
   @Named("stage")
   String stageName;
}


来源:https://stackoverflow.com/questions/1564762/how-to-bind-string-to-variable-in-guice

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!