Использование Assisted Inject с FactoryModuleBuilder в подсказке - Фабричное внедрение не выполняется

Я новичок, пытающийся выяснить, как внедрить вспомогательную инъекцию с помощью FactoryModuleBuilder. Я обратился к руководству по Java для реализации FactoryModuleBuilder.

Я сделал все именно так, как сказано в документах. Его не вводят на заводе. Я ссылался на этот вопрос переполнения стека: Guice AssistedInject не будет внедрять фабрику, которая имела ту же проблему. В нем говорится о введении поля до задачи инжектора конструктора. Я последовал за этим, и я пытаюсь вызвать класс Parent, используя класс вызывающего, но я все еще получаю исключение нулевого указателя. Что здесь не так?

Класс звонящего

public class MAIN {

    @Inject private static MyFactory factory;

    public static void main(String[] args){
        ParentClass newbie = new ParentClass(factory);
    }
}

Я все еще получаю исключение:

Exception in thread "main" java.lang.NullPointerException
    at com.pkg.ParentClass.<init>(ParentClass.java:19)
    at com.pkg.MAIN.main(MAIN.java:10)

Родительский класс

public class ParentClass {

    private final Foo test;
    @Inject
    public ParentClass(MyFactory factory){
        test = factory.create(new HashMap<String,Object>());
    }
}

Реализация модуля: ParentModule

public class ParentModule extends AbstractModule{

    @Override
    protected void configure() {
        install(new FactoryModuleBuilder()
                .implement(Foo.class, FooImpl.class)
                .build(MyFactory.class));
    }

}

Заводской интерфейс: MyFactory

public interface MyFactory {

    Foo create(Map<String,Object> map);
}

Интерфейс класса: Foo

public interface Foo{
}

Класс:FooImpl

public class FooImpl implements Foo {

    private final Map<String,Object> mapA;
    @AssistedInject
    public FooImpl(@Assisted Map<String,Object> map){

        mapA=map;
    }

}

1 ответ

Решение

У вас есть две проблемы здесь.

Первое и самое важное, вы не создаете Injector в любом месте. Очевидно, без инжектора ничего не получится. Вы должны создать экземпляр инжектора, используя ваш модуль:

Injector injector = Guice.createInjector(new ParentModule());

Ваша вторая проблема заключается в том, что вы хотите внедрить свою фабрику в статическое поле:

@Inject private static MyFactory factory;

Хотя Guice может работать со статическими полями, если вы укажете это явно, это считается очень плохой практикой. Никогда не вставляйте в статические поля, если вы не работаете с устаревшим кодом.

Что вы действительно хотите, это что-то вроде этого:

public class Main {
    @Inject
    private MyFactory factory;

    public void run() {
        ParentClass newbie = new ParentClass(factory);
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new ParentModule());
        Main main = injector.getInstance(Main.class);
        main.run();
    }
}

Обратите внимание, что точка входа в программу (main) теперь создает инжектор, а затем использует его для создания экземпляра Main класс, в который будет вставлено его поле автоматически. И тогда это вызывает метод run() на экземпляр, который выполняет фактическую работу.

Обратите внимание, однако, что все это действительно действительно только в иллюстративных целях для вспомогательной инъекции. Вы не должны структурировать свой реальный код таким образом. Например, вы используете new оператор для создания классов, чьи конструкторы помечены @Inject, Никогда не делай этого! Если вы пометите некоторый класс (т.е. его конструкторы или поля) как @InjectВ состоянии, то этот класс следует использовать только с помощью инъекций. Ваш Main код может быть сокращен до следующего:

public class Main {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new ParentModule());
        ParentClass newbie = injector.getInstance(ParentClass.class);
    }
}

Вот newbie автоматически получит экземпляр MyFactory в его конструктор, так как он помечен @Inject,

И я уже писал о статике.

Другие вопросы по тегам