Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
261 views
in Technique[技术] by (71.8m points)

java - Inject variable with custom parameter without creating 2 guice helper interfaces?

I'm using guice to dynamically inject classes in my constructors. For example:

@Inject
public PublisherFrame(EventBus eventBus, MyPublisherService publishService)

And in my guice module:

bind(EventBus.class).in(Singleton.class);
bind(MyPublisherService.class).in(Singleton.class);

Works without problems.

The problem starts when i create a object which has a parameter which is constructed in java code:

public LoginController(EventBus eventBus, MyPublisherService publisherService, LoginDialog dlg)

Here LoginDialog is a java class which java codes create. To solve this i use @assist and:

install(new FactoryModuleBuilder().implement(ILoginController.class, LoginController.class).build(GuiceLoginControllerFactory.class));

Works also nicely. But now i have to create 2 extra java files:

  • a new interface for LoginController: ILoginController, which doesn't do anything except help guice.
  • another interface for guice: GuiceLoginControllerFactory

Is there an easier way to inject a variable which has a custom parameter in the constructor? (without creating 2 extra "guice" helper files)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You don't actually need the additional interface for the class itself (see below). Furthermore, I generally create my factory as a nested interface of the class it creates:

public class LoginController {
  public interface Factory {
    LoginController create(LoginDialog dlg);
  }

  @Inject public LoginController(
      EventBus eventBus,
      MyPublisherService publisherService,
      @Assisted LoginDialog dlg) { /* ... */ }
}

// in your module
install(new FactoryModuleBuilder().build(LoginController.Factory.class));

You don't need to call FactoryModuleBuilder.implement unless you want your Factory's factory method's return type to be an interface rather than a concrete class--then Guice won't know what kind of concrete type to construct without your help. In the example below, you couldn't ask FactoryModuleBuilder to simply implement LoginService.Factory for you, as it would have no idea which concrete LoginService implementor to instantiate:

interface LoginService {
  interface Factory {
    LoginService create(NetConnection connection);
  }
  boolean login(String username, String password);
}

class SimpleLoginService implements LoginService {
  @Inject SimpleLoginService(@Assisted NetConnection connection) { /* ... */ }
}

class SecuredLoginService implements LoginService {
  @Inject SecuredLoginService(
      EncryptionService encryptionService,
      @Assisted NetConnection connection) { /* ... */ }
}

// in your module: implements LoginService.Factory
install(new FactoryModuleBuilder()
    .implement(LoginService.class, SimpleLoginService.class)
    .build(LoginService.Factory.class));
// this one implements @Secured LoginService.Factory
install(new FactoryModuleBuilder()
    .implement(LoginService.class, SecuredLoginService.class)
    .build(Key.get(LoginService.Factory.class, Secured.class));

Barring that, condit's idea of creating a setter method isn't bad, though that does mean that you are constructing your class in a partially-initialized state.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...