Напомню, что все проекты из этой книги находятся по адресу https://manning-content.s3.amazonaws.com/download/a/32357a2-2420-4c0f-be67-645246ae0d94/code.zip.
Можно сказать, что интерфейс описывает «то, что должно случиться», а каждый отдельный объект — «то, как именно это должно случиться».
Можно сказать, что интерфейс описывает «то, что должно случиться», а каждый отдельный объект — «то, как именно это должно случиться».
В зависимости от конкретной реализации возможны следующие варианты.
1. Идентификатор параметра совпадает с именем одного из бинов, добавленных в контекст (которое, напомню, в свою очередь, идентично имени метода, снабженного аннотацией @Bean и возвращающего значение этого бина). В подобном случае Spring выберет бин с таким же именем, как и у параметра.
2. Идентификатор параметра не совпадает ни с одним из имен бинов, имеющихся в контексте. Тогда можно поступить следующим образом:
• отметить один из бинов как первичный (с помощью аннотации @Primary, как в главе 2). В этом случае Spring выберет для внедрения первичный бин;
• выбрать некий бин и отметить его аннотацией @Qualifier, как будет описано далее;
• не делать ничего из выше перечисленного — однако в подобном случае приложение завершится ошибкой и выдаст исключение, сообщающее о том, что в контексте есть несколько бинов одного типа и Spring не может выбрать один из них.
Циклическая зависимость (рис. 3.11) — это ситуация, когда для создания бина (назовем его Bean A) Spring должен внедрить зависимость от другого бина, пока еще не существующего (Bean B). Но Bean B, в свою очередь, также требует зависимости от Bean A. И Spring заходит в тупик: он не может создать Bean A, так как для этого нужен Bean B, и не может создать Bean B, так как для этого нужен Bean A.
Начиная со Spring 4.3, если класс состоит только из одного конструктора, аннотацию @Autowired можно пропустить.
Он позволяет объявлять поля как final, таким образом гарантируя, что никто не сможет изменить значения этих полей после их инициализации в Spring. Присваивание значений при вызове конструктора также поможет вам при написании специфических модульных тестов, где нельзя полагаться на то, что Spring сам сделает внедрение в поле класса
возможности отметить это поле как final (см. следующий фрагмент кода) и таким образом гарантировать, что никто не сможет изменить его после того, как оно будет использовано:
• при инициализации приходится самостоятельно управлять значением, а это сложнее.
технология DI состоит в том, что фреймворк присваивает значение определенному полю или параметру.
Когда я объясняю этот способ студентам, кто-нибудь обязательно задает вопрос: не создается ли при этом два экземпляра типа Parrot (рис. 3.5) — один при добавлении в контекст Spring и еще один, когда метод person() напрямую вызывает метод parrot()? Нет. На самом деле в приложении существует только один экземпляр parrot.
