2010-08-04 2 views
10

У меня есть класс, как это так, что я создаю себе где-то в моем коде:Guice Вводит поле в классе не создано Guice

class StarryEyes { 
    @Inject MyValidator validator; 

    public StarryEyes(String name) { 
     //.. 
    } 

    public doSomething() { 
     // validator is NULL 
    } 
} 

Я хочу Guice внедрить экземпляр валидатора, который имеет @Singleton аннотаций. У меня есть модуль, который загружается при запуске и содержит строку:

bind(MyValidator.class); 

Однако, это не похоже на работу, как «валидатор» всегда нулевой. Я пробовал несколько вариантов:

bind(MyValidator.class)toInstance(new MyValidator()); 

или другие подобные вещи. Разве это не так, как должен работать Гийс?

ответ

33

Обычно Guice должен создавать объекты для их инъекции. Если вы просто вызываете new StarryEyes(name), Guice никогда не увидит этот объект, поэтому он не сможет его ввести. Одна вещь, которую вы можете сделать, - вызвать injector.injectMembers(obj) на объект после того, как вы его создали. Однако я бы не рекомендовал этого, так как вам следует избегать ссылки на инжектор в вашем коде.

Возможно, вы действительно хотите здесь Assisted Inject. С Assisted Inject, вы бы объявить конструктор для класса что-то вроде этого:

@Inject public StarryEyes(MyValidator validator, @Assisted String name) 

Что это означает, что validator является параметром, который Guice следует вводить, в то время как name должен быть «помощь» (то есть, при условии на момент создания экземпляра).

Вы затем создать интерфейс, как это:

public interface StarryEyesFactory { 
    StarryEyes create(String name); 
} 

С Assisted Inject, Guice может затем осуществить эту фабрику для вас. Вы связываете это так:

bind(StarryEyesFactory.class).toProvider(
    FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class)); 

Вы затем впрыснуть StarryEyesFactory в любом месте вы хотите создать экземпляр. Если бы вы раньше звонили new StarryEyes(name), вместо этого вы вызываете starryEyesFactory.create(name). Когда вы назовете create(name) на заводе, он примет имя и передаст его конструктору и предоставит связанный валидатор.

Начиная с Guice 3, вы делаете это с помощью FactoryModuleBuilder:

install(new FactoryModuleBuilder().build(StarryEyesFactory.class));