Статьи

@Autowired и необязательные зависимости

@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 со следующими зависимостями (разрешены все комбинации):

  1. DependencyA, DependencyB
  2. DependencyA, DependencyB, DependencyC
  3. DependencyA, DependencyB, DependencyD
  4. DependencyA, DependencyB, DependencyC, DependencyD

И это все замечательно, но уверены ли вы, что все эти комбинации действительно полезны и правильны? Что, если автор класса подумал только о 1 и 4?

Необязательные зависимости — делайте это правильно!

Если мы рассмотрим пример, представленный в предыдущем абзаце, есть два возможных ответа на заданный вопрос:

  1. Все комбинации возможны.
  2. Возможно только подмножество комбинаций.

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

Как насчет второго пункта — подмножества комбинаций?

Предположим, что только создание объекта в состоянии из точек 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» .