Как работает аннотация @Inject?

115
08 декабря 2019, 13:50

Я новичок только учу @Inject. Я не очень понимаю, как он работает. Вот у меня есть поле:

@Injection private A a;

И я могу использовать в своем коде a, хотя я не писал new. Правильно я понимаю, что @Inject просто объявляет a = new A? А что делать, если у меня класс B наследуется от A и я хочу сделать a = new B;?

И зачем так писать, почему не написать A a = new A(); ???

Спасибо все помогли

Появился еще вопрос Если аннотация лучше то мне теперь всегда в полях использовать аннотации вместо new?

Answer 1

Начнем по порядку

Вопрос: Правильно я понимаю, что @Inject просто объявляет a = new A?
Ответ: Не всегда. Все зависит от scopa для бина. Если scope выставлен как prototype то да, для каждого поля будет создаваться новый объект. Но как правило, например в spring значение по умолчанию это singleton. те создается один объект который затем присвается всем полям

Вопрос: А что делать, если у меня класс B наследуется от A и я хочу сделать a = new B?
Ответ: Ничего, с вашей стороны, никаких действий не требуется. DI фреймворки достаточны умны, чтобы обрабатывать подобные ситуации

Вопрос: И зачем так писать, почему не написать A a = new A()?
Ответ: Все это нужно для уменьшения связанности. Это позволяет более гибко изменять реализацию. Обычно, в роли А выступает какой нибудь интерфейс. И если в коде вы напишете А а = new AImpl(); то в какой то момент, когда захотите поменять реализацию на NewAImpl вам потребуется везде изменять код. Это не удобно, если таких мест много. А если учитывать, что в каждом бине есть свои зависимости, то задача усложняется еще больше

Answer 2

Эта концепция называется Внедрение зависимостей или dependency injection, в целом она позволяет получить более лаконичный код, уменьшить связность, и уменьшить возможные трудозатраты на поддержку кода в дальнейшем(задел на будущее).

Суть в следующем, есть объект-инжектор, при старте приложения Вы говорите ему: создай мне экземпляр класса A, он создает его, затем при помощи reflection ищет все поля, помеченные аннотацией @Inject и создает их вышеописанным же образом.

Польза в этом следующая: при разработке отдельных модулей Вы можете не оперировать конкретными объектами, а писать интерфейсы и создавать их экземпляры, не зная при этом их фактической реализации. Например когда вы пишете @Inject MyInterface foo; при этом при конфигурации инжектора у вас указано что, мол, когда встретишь MyInterface создавай MyImplementation.class, то инжектор создаст класс MyImplementation.class и присвоит полю foo ссылку на него

Но и недостатки тоже есть - в некоторых ситуациях сложно будет писать юнит тесты, так же, вы можете узнать каким будет класс только в рантайме, т.е. если в проекте сложная логика, не всегда очевидно что в поле заинжектится, последнее затрудняет например навигацию в ide, и еще один немаловажный фактор - порог вхождения(иначе бы не пришлось Вам это здесь расписывать), т.е. если Вы втягиваете DI в свой проект, новички могут слегка просесть по началу, увидев его.

Answer 3

Суть в том, что какой именно из наследников будет в поле private A a определяет не тот класс, в котором это поле объявлено. Чтобы можно было подсунуть любую реализацию класса/интерфейса A извне. Т.е. если вы напишите A a = new B(); в каждом классе, в котором будет использоваться эта реализация A, то потом если вас попросят заменить на новый класс - например на новый наследник C implements A то вам придется руками это исправлять в каждом классе. А если речь идет о сотнях классов, то это будет тяжело

READ ALSO
Права доступа к папке в Android

Права доступа к папке в Android

В ходе работы приложения создаю папку и помещаю туда фото с камеры

137
Hibernate. NoClassDefFoundError

Hibernate. NoClassDefFoundError

У меня есть Maven проект на 2 модуляВо втором модуле я поставил Hibernate

140
Как создавать папку в папке

Как создавать папку в папке

Хотел бы узнать, как можно создать папку в папке, вызывая одну функцию

136
Android Studio Возникает ошибка java.lang.NullPointerException

Android Studio Возникает ошибка java.lang.NullPointerException

Помогите пожалуйста решить проблему

154