@Autowired аннотация делает нашу жизнь проще. Это также может привести к уменьшению объема кода, если мы используем его в свойствах класса. Нам не нужны ни конструкторы, ни методы установки. На первый взгляд это выглядит великолепно, но преимущества редко бывают без затрат.
Сегодня я хочу, чтобы вы знали о расходах, которые должны быть оплачены.
@Autowired (обязательно = ложь)
В аннотации @Autowired по умолчанию для элемента требуется значение true, что означает, что аннотированная зависимость обязательна. Однако мы можем отключить поведение по умолчанию и сделать зависимость необязательной следующим образом:
1
2
|
@Autowired (required= false ) private Dependency dependency; |
Это может быть полезно, и поскольку не все зависимости требуются всегда, введение такой возможности было разумным.
Так в чем же проблема с зависимостями, аннотированными таким образом?
Давайте посмотрим на код:
01
02
03
04
05
06
07
08
09
10
|
class SomeClass { @Autowired private DependencyA dependencyA; @Autowired private DependencyB dependencyB; @Autowired (required= false ) private DependencyC dependencyC; @Autowired (required= false ) private DependencyD dependencyD; } |
Мы можем создать экземпляр SomeClass со следующими зависимостями (разрешены все комбинации):
- DependencyA, DependencyB
- DependencyA, DependencyB, DependencyC
- DependencyA, DependencyB, DependencyD
- DependencyA, DependencyB, DependencyC, DependencyD
И это все замечательно, но уверены ли вы, что все эти комбинации действительно полезны и правильны? Что, если автор класса подумал только о 1 и 4?
Необязательные зависимости — делайте это правильно!
Если мы рассмотрим пример, представленный в предыдущем абзаце, есть два возможных ответа на заданный вопрос:
- Все комбинации возможны.
- Возможно только подмножество комбинаций.
В случае, когда возможны все комбинации, я бы оставил код как есть. Если нет ничего, что могло бы пойти не так, и каждое состояние объекта правильное, то наш код достаточно описательный. Это явно позволяет все, поэтому мы можем предположить, что все, что мы сделаем, приведет к созданию объекта, с которым мы можем работать.
Как насчет второго пункта — подмножества комбинаций?
Предположим, что только создание объекта в состоянии из точек 1 и 4 является допустимым. Оставление кода без изменений может привести к неправильному использованию объекта. Мы разрешаем создание объекта в недопустимых состояниях (пункты 2 и 3). Что мы можем сделать по этому поводу?
В этом случае я думаю, что мы должны отказаться от аннотации @Autowired. Ради читабельности кода и качества дизайна было бы лучше использовать конструкторы:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
class SomeClass { private DependencyA dependencyA; private DependencyB dependencyB; private DependencyC dependencyC; private DependencyD dependencyD; public SomeClass(DependencyA dependencyA, DependencyB dependencyB) { this .dependencyA = dependencyA; this .dependencyB = dependencyB; } public SomeClass(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC, DependencyD dependencyD) { this (dependencyA, dependencyB); this .dependencyC = dependencyC; this .dependencyD = dependencyD; } } |
С помощью этого кода вы знаете все, что нужно. Вы знаете, какие зависимости необходимы для создания правильного объекта.
Будьте в курсе!
Эта статья не предназначена для того, чтобы убедить вас, что лучше не использовать @Autowired (обязательно = false). Его цель — информировать вас о стоимости, которую вы должны заплатить.
Вы должны защитить свой дизайн, вы должны защитить инварианты объектов, и вы не должны допускать существование объектов в недопустимом состоянии. Конечно, вы можете добавить документацию или комментарий, но если у нас уже есть семантика, предоставляемая языком, которая позволяет нам сделать это без дополнительных усилий, мы должны ее использовать.
Ссылка: | @Autowired и необязательные зависимости от нашего партнера по JCG Себастьяна Малаки в блоге « Давайте поговорим о Java» . |