Впръскване на зависимостта на конструктора през пролетта

1. Въведение

Може би един от най-важните принципи за развитие на съвременния софтуерен дизайн е Dependency Injection (DI), който съвсем естествено произтича от друг критично важен принцип: Модулност.

Тази статия ще изследва специфичен тип DI техника, наречена конструктор-базирано инжектиране на зависимост в Spring - което просто казано означава, че необходимите компоненти се предават в клас по време на създаването на инстанция.

За да започнем, трябва да импортираме зависимостта spring-context в нашия pom.xml :

 org.springframework spring-context 5.2.8.RELEASE 

След това трябва да настроим конфигурационен файл. Този файл може да бъде или POJO, или ако предпочитате, XML файл.

2. Конфигурация на базата на анотации

Java конфигурационният файл изглежда почти като обикновен стар Java обект с някои допълнителни пояснения:

@Configuration @ComponentScan("com.baeldung.constructordi") public class Config { @Bean public Engine engine() { return new Engine("v8", 5); } @Bean public Transmission transmission() { return new Transmission("sliding"); } } 

Тук използваме анотации, за да уведомим пролетното време на изпълнение, че този клас е доставчик на дефиниции на боб ( анотация @Bean ) и че трябва да се извърши контекстно сканиране за допълнителни зърна в пакета com.baeldung.spring . След това дефинираме клас Car :

@Component public class Car { @Autowired public Car(Engine engine, Transmission transmission) { this.engine = engine; this.transmission = transmission; } }

Spring ще срещне нашия клас Car, докато прави сканиране на пакети, и ще инициализира своя екземпляр, като извика @Autowired анотиран конструктор.

Екземпляри на Engine и Transmission ще бъдат получени чрез извикване на @Bean коментирани методи от класа Config . И накрая, трябва да стартираме ApplicationContext, използвайки нашата конфигурация POJO:

ApplicationContext context = new AnnotationConfigApplicationContext(Config.class); Car car = context.getBean(Car.class);

3. Неявно инжектиране на конструктор

От пролет 4.3 класовете с един конструктор могат да пропуснат анотацията @Autowired . Приятно малко удобство и отстраняване на бойлер!

На всичкото отгоре, също като се започне с 4.3, инжектирането на базата на конструктор може да се използва в анотираните класове @Configuration . И да, ако такъв клас има само един конструктор, @Autowired анотацията също може да бъде пропусната.

4. XML базирана конфигурация

Друг начин за конфигуриране на времето за изпълнение на Spring с инжектиране на зависимости, базирана на конструктор, е използването на XML конфигурационен файл:

Имайте предвид, че constructor-arg може да приеме буквална стойност или препратка към друг компонент и че могат да бъдат предоставени незадължителен изричен индекс и тип . Атрибутите на типа и индекса могат да се използват за разрешаване на двусмислието (например, ако конструктор приема множество аргументи от същия тип).

атрибут name също може да се използва за съвпадение на променливи от xml към java, но тогава вашият код трябва да бъде компилиран с включен флаг за отстраняване на грешки.

В този случай контекст на приложение Spring трябва да бъде стартиран с помощта на ClassPathXmlApplicationContext :

ApplicationContext context = new ClassPathXmlApplicationContext("baeldung.xml"); Car car = context.getBean(Car.class);

5. Плюсове и минуси

Инжектирането на конструктор има няколко предимства в сравнение с инжектирането на полето.

Първата полза е проверимостта. Да предположим, че ще тестваме единично Spring bean, който използва инжектиране на поле:

public class UserService { @Autowired private UserRepository userRepository; }

По време на изграждането на екземпляр UserService не можем да инициализираме състоянието userRepository . Единственият начин да се постигне това е чрез API за отразяване, който напълно нарушава капсулирането. Също така полученият код ще бъде по-малко безопасен в сравнение с обикновен конструктор.

Освен това, с инжектиране на поле, не можем да приложим инварианти на ниво клас.Така че е възможно да имате екземпляр UserService без правилно инициализирано userRepository . Следователно тук и там може да изпитаме случайни NullPointerException . Освен това с инжектирането на конструктор е по-лесно да се изграждат неизменяеми компоненти.

Освен това използването на конструктори за създаване на екземпляри на обекти е по-естествено от гледна точка на ООП.

От друга страна, основният недостатък на инжектирането на конструктор е неговата многословност, особено когато боб има шепа зависимости. Понякога това може да бъде прикрито благословение, тъй като може да се опитаме по-усилено да поддържаме броя на зависимостите минимален.

6. Заключение

Този бърз урок показа основите на два различни начина за използване на инжектиране на зависимостта на базата на конструктор, използвайки Spring Spring.

Най- пълното прилагане на този урок може да се намери повече от GitHub.