Ответ 1
Одно фундаментальное отличие от инъекции метода, которое отличается от того, как вы его используете, заключается в том, что инъекция метода - это еще один способ для кинжала отправлять зависимости при построении или инъекции объекта DI-ready, что означает, что @Inject-аннотированные методы должны быть вызваны кинжалом один раз при построении, а не из вашего собственного кода. Это делает очень маловероятным, чтобы вы @Inject
-незаменили makeDinner
, fryDinner
или любой другой метод, который имеет значимые побочные эффекты или возвращаемые значения. Вместо этого обработайте инъекцию метода как возможность пост-факто для инъекций в стиле конструктора.
public class Chef {
private Provider<Pasta> mPastaProvider;
private Sauce mSauce;
@Inject
public void registerIngredients( // can be named anything
Provider<Pasta> pastaProvider,
Sauce sauce) { // T and Provider<T> both work, of course
mPastaProvider = pastaProvider;
mSauce = sauce;
}
/* [email protected] */ public Dinner cookDinner() {
mPan.add(mPastaProvider.get());
mPan.add(mSauce);
return mPan.cookDinner();
}
/* [email protected] */ public Dinner fryDinner() {
mPan.add(mPastaProvider.get());
mPan.add(mSauce);
return mPan.fryDinner();
}
}
В этом случае, когда вы запрашиваете инъекцию у шеф-повара, Кинжал увидит @Inject-аннотированный метод и вызовет его. Если у вас нет конструктора @Inject-annotated или @Provides, вы не сможете получить шеф-повар прямо из вашего компонента, но вы можете создать метод void
для компонента, который получает построенный экземпляр Chef
и который использует инъекцию полей и методов, чтобы обеспечить шеф-повару ингредиентами (или поставщиками ингредиентов), которые им могут понадобиться. (Подробнее см. В документах @Component и MembersInjector.)
Обратите внимание, что ни в коем случае не отображается Dinner
на графе объектов! Добавление @Inject в конструктор говорит Кинжалу, что он может использовать этот конструктор, чтобы сделать объект доступным на графе объектов, но добавление @Inject к методу или полю просто говорит кинжалу, что как часть процесса инъекции оно должно заполнить это поле или вызвать этот метод с данными зависимостями. Если вы хотите сделать ужин на графике объекта, вам нужно будет @Inject-аннотировать конструктор Dinner или поместить метод @Provides или @Binds в модуль, который вы подаете в компонент.
Зачем вам это использовать? Рассмотрим случай, когда объекты создаются рефлексивно (например, "Действия, фрагменты" и "Виды в Android" или "Сериализуемые объекты" ), где вы предпочитаете не открывать поля @Inject. В этих случаях вы можете обойти ограничения конструктора, если ваша инъекция произойдет в поле. Точно так же, хотя я и не пробовал этого, вы могли бы воспользоваться иерархией классов, чтобы отметить метод интерфейса с помощью @Inject, гарантируя, что независимо от того, находитесь ли вы в контексте DI, вы можете передать определенные зависимости объекту как часть их подготовка.