Я новичок только учу @Inject
. Я не очень понимаю, как он работает. Вот у меня есть поле:
@Injection
private A a;
И я могу использовать в своем коде a, хотя я не писал new
. Правильно я понимаю, что @Inject
просто объявляет a = new A?
А что делать, если у меня класс B
наследуется от A
и я хочу сделать a = new B;
?
И зачем так писать, почему не написать A a = new A(); ???
Спасибо все помогли
Появился еще вопрос Если аннотация лучше то мне теперь всегда в полях использовать аннотации вместо new?
Начнем по порядку
Вопрос: Правильно я понимаю, что @Inject
просто объявляет a = new A
?
Ответ: Не всегда. Все зависит от scopa
для бина. Если scope выставлен как prototype
то да, для каждого поля будет создаваться новый объект. Но как правило, например в spring
значение по умолчанию это singleton
. те создается один объект который затем присвается всем полям
Вопрос: А что делать, если у меня класс B
наследуется от A
и я хочу сделать a = new B
?
Ответ: Ничего, с вашей стороны, никаких действий не требуется. DI фреймворки достаточны умны, чтобы обрабатывать подобные ситуации
Вопрос: И зачем так писать, почему не написать A a = new A()
?
Ответ: Все это нужно для уменьшения связанности. Это позволяет более гибко изменять реализацию. Обычно, в роли А выступает какой нибудь интерфейс. И если в коде вы напишете А а = new AImpl();
то в какой то момент, когда захотите поменять реализацию на NewAImpl
вам потребуется везде изменять код. Это не удобно, если таких мест много. А если учитывать, что в каждом бине есть свои зависимости, то задача усложняется еще больше
Эта концепция называется Внедрение зависимостей или dependency injection
, в целом она позволяет получить более лаконичный код, уменьшить связность, и уменьшить возможные трудозатраты на поддержку кода в дальнейшем(задел на будущее).
Суть в следующем, есть объект-инжектор, при старте приложения Вы говорите ему: создай мне экземпляр класса A
, он создает его, затем при помощи reflection ищет все поля, помеченные аннотацией @Inject
и создает их вышеописанным же образом.
Польза в этом следующая: при разработке отдельных модулей Вы можете не оперировать конкретными объектами, а писать интерфейсы и создавать их экземпляры, не зная при этом их фактической реализации. Например когда вы пишете @Inject MyInterface foo;
при этом при конфигурации инжектора у вас указано что, мол, когда встретишь MyInterface
создавай MyImplementation.class
, то инжектор создаст класс MyImplementation.class
и присвоит полю foo
ссылку на него
Но и недостатки тоже есть - в некоторых ситуациях сложно будет писать юнит тесты, так же, вы можете узнать каким будет класс только в рантайме, т.е. если в проекте сложная логика, не всегда очевидно что в поле заинжектится, последнее затрудняет например навигацию в ide, и еще один немаловажный фактор - порог вхождения(иначе бы не пришлось Вам это здесь расписывать), т.е. если Вы втягиваете DI в свой проект, новички могут слегка просесть по началу, увидев его.
Суть в том, что какой именно из наследников будет в поле private A a
определяет не тот класс, в котором это поле объявлено. Чтобы можно было подсунуть любую реализацию класса/интерфейса A
извне. Т.е. если вы напишите A a = new B();
в каждом классе, в котором будет использоваться эта реализация A
, то потом если вас попросят заменить на новый класс - например на новый наследник C implements A
то вам придется руками это исправлять в каждом классе. А если речь идет о сотнях классов, то это будет тяжело
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
В ходе работы приложения создаю папку и помещаю туда фото с камеры
У меня есть Maven проект на 2 модуляВо втором модуле я поставил Hibernate
Хотел бы узнать, как можно создать папку в папке, вызывая одну функцию
Помогите пожалуйста решить проблему