Guice协助注入,绑定命令

时间:2016-10-19 22:17:49

标签: java guice

我在实施辅助注射时遇到了错误。

辅助注射工作直到我引入了另一个名为Manager的类,它依赖于辅助Person类。经理想要使用Person (@Assited Address)。代码在构造注入器图时打破了。它没有进一步发展。

Injector injector = Guice.createInjector(myModule); 

直观地说,我理解当对象A被辅助时,B(依赖于A)实际上也是通过A隐式辅助的。

请注意,我检查了SO。我认为像ColinD这样的人肯定会知道答案 How to use Guice's AssistedInject? How to bind Assisted Injected class to interface?

出于好奇,有没有很好的技巧/工具可以发现Guice的错误配置并简化学习曲线?我打开了ProvisionListener并使用了图库。这有点帮助。

public class Person implements PersonInterface {
private String name;
private Address address;

 @Inject
 public Person(String name, @Assisted Address address) {
        this.name = name;
        this.address = address;
 }

}

public interface PersonInterface {
  public String getName();
  public Address getAddress();
}

public interface PersonFactory {
  public PersonInterface create(Address address);
}

public class Address {
 private final String address;  

 public Address(String address) {
    super();
    this.address = address;
 }
}

public class Manager implements IManager {  
 private final Person person;   
 @Inject
 public Manager(Person person) {
    this.person=person;
 }
 ...
 }

 configure() {

    install(new FactoryModuleBuilder()
             .implement(PersonInterface.class, Person.class)
             .build(PersonFactory.class));

    //
    bind(IManager.class).to(Manager.class);
}

实际错误是

com.google.inject.CreationException: Unable to create injector, see the following errors:

1) No implementation for ...assisted_inject.Address annotated with @com.google.inject.assistedinject.Assisted(value=) was bound.
  while locating ....assisted_inject.Address annotated with @com.google.inject.assistedinject.Assisted(value=)
    for parameter 2 at ....assisted_inject.Person.<init>(Person.java:13)

1 个答案:

答案 0 :(得分:3)

将此绑定放入模块时:

bind(IManager.class).to(Manager.class);

Guice将尝试创建Manager类的新实例。它查找使用@Inject注释的一个(但只有一个)构造函数或作为非私有的后备零参数构造函数。这是Guice将使用的构造函数:

@Inject
public Manager(Person person) {
   this.person=person;
}

现在遵循相同的规则,Guice会尝试使用适当的构造函数来实例化Person,它会卡在这里:

@Inject
public Person(String name, @Assisted Address address) {
    this.name = name;
    this.address = address;
}

由于@Assisted注释,尝试实例化地址时会放弃。这个注释是BindingAnnotation,Guice特别对待它们 - 它试图找到它们的显式绑定,但没有。阅读有关绑定注释的内容,您将了解原因。

由于您的经理是有状态的并且显然管理着一个人,您可能想为这些经理创建一个工厂,例如:

public interface IManagerFactory {
    public IManager getIManager(PersonInterface p);
}

然后你会有一个IManager,例如:

public interface IManager {
    public String getPersonName();
}

使用辅助注射的实现:

public class Manager implements IManager {
    private final PersonInterface person;

    @Inject
    public Manager(@Assisted PersonInterface person) {
        this.person = person;
    }

    @Override
    public String getPersonName() {
        return person.getName();
    }

}

您可以在模块中绑定它们:

class MyModule extends AbstractModule {
     protected void configure() {
        install(new FactoryModuleBuilder()
           .implement(PersonInterface.class, Person.class)
                 .build(PersonFactory.class));


        install(new FactoryModuleBuilder()
            .implement(IManager.class, Manager.class)
            .build(IManagerFactory.class));
      }
    }

注入工厂:

@Inject
PersonFactory pf;

@Inject
IManagerFactory manF;

并相应地使用它们,例如:

public void testGuice() {
    PersonInterface pi = pf.create(new Address("boh"));
    IManager im = manF.getIManager(pi);

    System.out.println(im.getPersonName());
}