Почему @Autowired иногда вообще не нужен?
Почему @Autowired иногда вообще не нужен?
После двух постов про транзакции и Proxy предлагаю немного отойти от AOP и посмотреть на DI.
Наверняка вы не раз писали:
Выглядит привычно, но есть нюанс:
@Autowired здесь можно спокойно удалить.
И Spring всё равно поймёт, что нужно внедрить PaymentService.
Почему?
Начиная со Spring 4.3, если у класса только один конструктор, Spring автоматически использует его для dependency injection.
То есть:
для Spring достаточно, чтобы понять:
.
А если конструкторов несколько:
тут Spring уже не может просто угадать. И тогда можно явно указать:
А почему тогда все продолжают писать @Autowired?
Потому что это старый и привычный стиль.
Современный Spring-код чаще выглядит так:
И здесь есть ещё один приятный бонус, зависимость становится обязательной: объект невозможно создать без PaymentService.
В отличие от field injection
где зависимость появляется уже после создания объекта.
Поэтому хороший ответ звучит не так:
А точнее:
И это один из тех маленьких нюансов Spring, которые вроде бы знаешь...но часто упускаешь при прямом вопросе
После двух постов про транзакции и Proxy предлагаю немного отойти от AOP и посмотреть на DI.
Наверняка вы не раз писали:
@Service
public class OrderService {
private final PaymentService paymentService;
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
Выглядит привычно, но есть нюанс:
@Autowired здесь можно спокойно удалить.
@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
И Spring всё равно поймёт, что нужно внедрить PaymentService.
Почему?
Начиная со Spring 4.3, если у класса только один конструктор, Spring автоматически использует его для dependency injection.
То есть:
public OrderService(PaymentService paymentService) {
...
}
для Spring достаточно, чтобы понять:
«Так, этому Bean нужен PaymentService. Найду его в контейнере и передам сюда»
.
А если конструкторов несколько:
public OrderService() {
}
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
тут Spring уже не может просто угадать. И тогда можно явно указать:
@Autowired
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService; }
А почему тогда все продолжают писать @Autowired?
Потому что это старый и привычный стиль.
Современный Spring-код чаще выглядит так:
@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService; }
}
И здесь есть ещё один приятный бонус, зависимость становится обязательной: объект невозможно создать без PaymentService.
В отличие от field injection
@Autowired
private PaymentService paymentService;
где зависимость появляется уже после создания объекта.
Поэтому хороший ответ звучит не так:
«@Autowired нужен для Dependency Injection
А точнее:
Spring умеет делать constructor injection без @Autowired, если у Bean единственный конструктор
И это один из тех маленьких нюансов Spring, которые вроде бы знаешь...но часто упускаешь при прямом вопросе