Какова цель пометки конструктора инъекций атрибутом @Autowired? - PullRequest
1 голос
/ 13 мая 2019

Я пытаюсь обернуть голову вокруг аннотации @Autowired.Я прочитал об этом, но это все еще не имеет большого смысла для меня

Конкретный случай, на который я обращаю внимание, - это передача хранилища в класс микро-обслуживания

Почему мыделай

@Autowired
public SomeClass (Repo repo) {
    this.repo = repo;
}

вместо простого

public SomeClass (Repo repo) {
    this.repo = repo;
}

Ответы [ 4 ]

1 голос
/ 13 мая 2019

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

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

Если я не ошибаюсь, более новые версии Spring позволяют пропустить атрибут.

0 голосов
/ 13 мая 2019

В аннотации @Autowired автоматически используется Bean (ресурс с пружинным управлением) типа Repo из контекста приложения, если таковой существует.Если ваш метод SomeClass сам по себе является «Bean» (аннотированным с помощью @Component, @Service или @Repository), то Spring будет гарантировать, что bean-компонент типа Repo существует в контексте приложения, прежде чем создавать экземпляр вашего компонента SomeClass.

Эта статья полезна: https://www.baeldung.com/spring-autowire

Как уже упоминали другие в этой теме, внедрение в конструктор облегчает модульное тестирование.Один из способов обойти это - создать статический класс, аннотированный @TestConfiguration, который содержит компоненты, необходимые для тестового контекста.

В этой статье есть некоторая информация об этом: https://www.baeldung.com/spring-boot-testing

Сайт Baeldung - отличный ресурс, если вы новичок в весне.

0 голосов
/ 13 мая 2019

Вы можете сделать это:

public SomeClass (Repo repo) {
    this.repo = repo;
}

если вы планируете создать объект самостоятельно. Но так как вы хотите, чтобы контейнер создавал ваши объекты (бины), вы указываете ему вводить вашу Repo зависимость во время создания SomeClass bean-компонента. Вы делаете это, добавляя @Autowired поверх вашего конструктора.

Вы также можете сделать это (инъекция в поле):

@Component
public class SomeClass {
    @Autowired
    private Repo repo;
} 

Но для облегчения модульного тестирования предпочтительнее внедрение в конструктор. Обратите внимание, что начиная с Spring 4.3 @Autowired больше не требуется в конструкторе.

EDIT

Лучше, при использовании Lombok вы можете сделать это:

@Component
@RequiredArgConstructor
public class SomeClass {

    private final Repo repo;
}

Ломбок сгенерирует конструктор

public SomeClass (Repo repo) {
    this.repo = repo;
}

для вас и контейнер будет вводить зависимость.

0 голосов
/ 13 мая 2019

Если у вас есть несколько конструкторов, вы должны указать пружине, какой конструктор использовать.Бесполезно большую часть времени.

Проверьте здесь: https://www.baeldung.com/constructor-injection-in-spring

Начиная с Spring 4.3, классы с одним конструктором могут опускать аннотацию @Autowired.Приятное немного удобства и удаление шаблонного!

...