Инъекция поля кинжала не работает с простыми классами Java

Я пытаюсь внедрить поле с помощью кинжала, хотя внедрение конструктора работает абсолютно нормально, но я не знаю, что не так с внедрением поля. Может быть, я делаю неправильно. Я добавляю фрагменты кода. Я получаю исключение нулевого указателя на engine.start(), потому что зависимость двигателя не подается. Это похоже на зависимости A->B->C, где A->B подается, а B->C нет. Давно не могу решить.

package com.raghav.java.car;

import javax.inject.Inject;

public class App 
{
    @Inject 
    Car car;

    App() {
        DaggerCarComponent.create().inject(this);
    }

    public static void main( String[] args )
    {
        App app = new App();
        app.perform();
    }

    private void perform() {
        car.run();

    }
}

public interface Engine {
    void start();
}

class FordEngine implements Engine {

    public void start() {
        System.out.println("Engine started -- Vroom Vroom");
    }
}

public interface Car {
        void run();
}

class MarutiCar implements Car {

    @Inject
    Engine engine;

    public void run() {
        engine.start();
        System.out.println("WOW!! Maruti Running ");        
    }

}

@Singleton
@Component(modules = {CarModule.class})
public interface CarComponent {

    void inject(App app);

}

@Module
class CarModule {

    @Singleton
    @Provides
    public Car provideCar() {
        return new MarutiCar();
    }


    @Singleton
    @Provides
    public Engine provideEngine() {
        return new FordEngine();
    }
}

person Raghav Sharma    schedule 21.05.2017    source источник


Ответы (1)


если вы хотите сделать вложенную инъекцию, вам нужно использовать инъекцию конструктора, иначе это не произойдет автоматически, потому что, когда вы предоставляете зависимость из стиля кинжала (через инъекцию конструктора или инъекцию аргумента в модуль), кинжал не знает об этом. измените свои классы, как показано ниже:

измените свой MarutiCar следующим образом:

class MarutiCar implements Car {

Engine engine;

@Inject
public MarutiCar(Engine engine)
{
    this.engine = engine;
}

public void run() {
    engine.start();
    System.out.println("WOW!! Maruti Running ");        
    }

}

и ваш класс FordEngine выглядит так:

class FordEngine implements Engine {

@inject
public FordEngine()
{
}

public void start() {
    System.out.println("Engine started -- Vroom Vroom");
    }
}

затем измените свой CarModule, как показано ниже:

@Module
class CarModule {

@Singleton
@Provides
public Car provideCar(MarutiCar marutiCar) {
    return marutiCar;
    }

@Singleton
@Provides
public Engine provideEngine(FordEngine fordEngine) {
    return fordEngine;
    }
}

ОБНОВЛЕНИЕ: DAGGER НЕ ВВОДИТ ПОЛЯ КЛАССА, КОТОРЫЙ НЕ СОЗДАН САМОСТОЯТЕЛЬНО.

вы создаете экземпляр MarutiCar самостоятельно, как вы ожидаете, что кинжал знает, что ему нужно? вы можете начать новую цепочку создания кинжалов в этом классе, чтобы добиться этого, что довольно странно. вам нужно сообщить кинжалу, что вам нужно, показав зависимости через аргумент метода конструктора или модуля, чтобы кинжал создал их экземпляр, чтобы вы знали, что им нужно. dagger не предоставляет ваши вложенные поля зависимостей, потому что он не создал их, поэтому он понятия не имеет об их зависимостях, если только вы не начнете еще одну цепочку создания кинжала, как то, что вы сделали в своем классе App. есть еще один способ, если вы не хотите использовать инъекцию конструктора, который я покажу вам только для класса Car и MarutiCar:

@Module
class CarModule {

@Singleton
@Provides
public Car provideCar(Engine engine) {
    MarutiCar marutiCar = new MarutiCar(engine);
    }

@Singleton
@Provides
public Engine provideEngine(FordEngine fordEngine) {
    return fordEngine;
    }
}

и класс MarutiCar будет таким (нет необходимости в @inject)

class MarutiCar implements Car {

Engine engine;

public MarutiCar(Engine engine)
{
    this.engine = engine;
}

public void run() {
    engine.start();
    System.out.println("WOW!! Maruti Running ");        
    }

}
person Amir Ziarati    schedule 21.05.2017
comment
Инъекция конструктора работает абсолютно нормально, как написано выше, но почему инъекция поля не работает? и можете ли вы показать экземпляр, в котором написано для вложенной инъекции, вам нужно использовать инъекцию конструктора, иначе это не произойдет автоматически. Почему невозможно внедрить поле во вложенных зависимостях. И есть один вопрос stackoverflow.com/questions/28330117/, который показывает, что внедрение поля возможно в dagger1, тогда почему это невозможно в dagger2. И спасибо за ответ! - person Raghav Sharma; 21.05.2017
comment
stackoverflow.com/questions/21694326/ посмотреть по этой ссылке. это объясняет, почему это происходит. - person Amir Ziarati; 22.05.2017
comment
Dagger отвечает за создание ваших зависимостей, чтобы они не вводили свои введенные поля, если только вы не создадите в них компонент. dagger предоставляет только те зависимости, которые необходимы для создания экземпляра (добавление @inject к конструкции). он не выполняет поиск и вставку для каждого поля в этой зависимости. - person Amir Ziarati; 22.05.2017
comment
если вы не хотите использовать инъекцию конструктора, вы можете добавить Engine к аргументам метода предоставления автомобиля. создайте экземпляр marutiCar, затем установите двигатель автомобиля. - person Amir Ziarati; 22.05.2017
comment
другой пост, поддерживающий это: github.com/square/dagger/issues/367 - person Amir Ziarati; 22.05.2017
comment
Спасибо @Amir Ziarati за ваше руководство. Видео Джейка Уортона devoxx 2014 также помогло понять концепцию. - person Raghav Sharma; 22.05.2017