Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

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

#java #java_ee


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

@Injection
private A a;

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

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

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

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


Ответы

Ответ 1



Начнем по порядку Вопрос: Правильно я понимаю, что @Inject просто объявляет a = new A? Ответ: Не всегда. Все зависит от scopa для бина. Если scope выставлен как prototype то да, для каждого поля будет создаваться новый объект. Но как правило, например в spring значение по умолчанию это singleton. те создается один объект который затем присвается всем полям Вопрос: А что делать, если у меня класс B наследуется от A и я хочу сделать a = new B? Ответ: Ничего, с вашей стороны, никаких действий не требуется. DI фреймворки достаточны умны, чтобы обрабатывать подобные ситуации Вопрос: И зачем так писать, почему не написать A a = new A()? Ответ: Все это нужно для уменьшения связанности. Это позволяет более гибко изменять реализацию. Обычно, в роли А выступает какой нибудь интерфейс. И если в коде вы напишете А а = new AImpl(); то в какой то момент, когда захотите поменять реализацию на NewAImpl вам потребуется везде изменять код. Это не удобно, если таких мест много. А если учитывать, что в каждом бине есть свои зависимости, то задача усложняется еще больше

Ответ 2



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

Ответ 3



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

Комментариев нет:

Отправить комментарий