Автор оригинала: Nguyen Nam Thai.
1. Движущие силы
В весеннем применении очень часто вводят один боб в другой боб. Однако иногда желательно ввести боб в обычный объект. Например, мы можем захотеть получить ссылки на службы из объекта сущности.
К счастью, достичь этого не так сложно, как может показаться. В следующих разделах будет показано, как это сделать с помощью @настраиваемой аннотации и AspectJ weaver.
2. Настраиваемая аннотация @
Эта аннотация позволяет экземплярам оформленного класса содержать ссылки на компоненты Spring.
2.1. Определение и регистрация Пружинного боба
Прежде чем перейти к аннотации @Configable , давайте настроим определение Spring bean:
@Service public class IdService { private static int count; int generateId() { return ++count; } }
Этот класс украшен аннотацией @Service ; следовательно, он может быть зарегистрирован в контексте Spring с помощью сканирования компонентов.
Вот простой класс конфигурации, включающий этот механизм:
@ComponentScan public class AspectJConfig { }
2.2. Использование @Конфигурируемых
В простейшей форме мы можем использовать @Конфигурируемый без какого-либо элемента:
@Configurable public class PersonObject { private int id; private String name; public PersonObject(String name) { this.name = name; } // getters and other code shown in the next subsection }
Аннотация @Конфигурируемая в данном случае отмечает объект Person класса как подходящий для конфигурации с пружинным приводом.
2.3. Инъекция пружинного боба в Неуправляемый объект
Мы можем внедрить Id Service в Person Object , как и в любом Spring bean:
@Configurable public class PersonObject { @Autowired private IdService idService; // fields, constructor and getters - shown in the previous subsection void generateId() { this.id = idService.generateId(); } }
Однако аннотация полезна только в том случае, если она распознана и обработана обработчиком. Именно здесь в игру вступает AspectJ weaver. В частности, | AnnotationBeanConfigurerAspect будет действовать на наличие @Конфигурируемый и выполняет необходимую обработку.
3. Включение плетения AspectJ
3.1. Объявление плагина
Чтобы включить плетение AspectJ, нам сначала нужен плагин AspectJ Maven :
org.codehaus.mojo aspectj-maven-plugin 1.11
И это требует некоторой дополнительной настройки:
1.8 ignore org.springframework spring-aspects
Первым необходимым элементом является Уровень соответствия . Значение 1.8 устанавливает как исходную, так и целевую версии JDK на 1.8. Если не установить явно, исходная версия будет 1.3, а целевая-1.1. Эти значения явно устарели и недостаточны для современного приложения Java.
Чтобы внедрить компонент в неуправляемый объект, мы должны полагаться на класс AnnotationBeanConfigurerAspect , предоставленный в spring-aspects.jar . Поскольку это предварительно скомпилированный аспект, нам нужно будет добавить содержащий артефакт в конфигурацию плагина.
Обратите внимание, что такой ссылочный артефакт должен существовать в качестве зависимости в проекте:
org.springframework spring-aspects 5.2.7.RELEASE
Мы можем найти последнюю версию spring-aspects на Maven Central .
3.2. Выполнение плагина
Чтобы проинструктировать плагин для создания всех соответствующих классов, нам нужна эта конфигурация executions :
compile
Обратите внимание цель плагина compile по умолчанию привязывается к фазе жизненного цикла компиляции.
3.2. Конфигурация бобов
Последний шаг для включения плетения AspectJ-это добавить @EnableSpringConfigured в класс конфигурации:
@ComponentScan @EnableSpringConfigured public class AspectJConfig { }
Дополнительная аннотация настраивает AnnotationBeanConfigurerAspect , который, в свою очередь, регистрирует экземпляры Person Object с контейнером Spring IoC.
4. Тестирование
Теперь давайте проверим, что служба Id bean была успешно введена в объект Person :
@RunWith(SpringRunner.class) @ContextConfiguration(classes = AspectJConfig.class) public class PersonUnitTest { @Test public void givenUnmanagedObjects_whenInjectingIdService_thenIdValueIsCorrectlySet() { PersonObject personObject = new PersonObject("Baeldung"); personObject.generateId(); assertEquals(1, personObject.getId()); assertEquals("Baeldung", personObject.getName()); } }
5. Инъекция Боба В Объект JPA
С точки зрения контейнера Spring сущность-это не что иное, как обычный объект. Таким образом, нет ничего особенного в том, чтобы ввести пружинный боб в объект JPA.
Однако, поскольку инъекция в объекты JPA является типичным случаем использования, давайте рассмотрим его более подробно.
5.1. Класс сущностей
Давайте начнем со скелета класса сущностей:
@Entity @Configurable(preConstruction = true) public class PersonEntity { @Id private int id; private String name; public PersonEntity() { } // other code - shown in the next subsection }
Обратите внимание на элемент preConstruction в аннотации @Configable : он позволяет нам вводить зависимость в объект до того, как он будет полностью построен.
5.2. Сервисное Впрыскивание
Теперь мы можем внедрить Id Service в Person Entity , аналогично тому, что мы сделали с Person Object :
// annotations public class PersonEntity { @Autowired @Transient private IdService idService; // fields and no-arg constructor public PersonEntity(String name) { id = idService.generateId(); this.name = name; } // getters }
Аннотация @Transient используется для того, чтобы сообщить JPA, что id Service – это поле, которое не должно сохраняться.
5.3. Обновление метода тестирования
Наконец, мы можем обновить метод тестирования, чтобы указать, что служба может быть введена в объект:
@Test public void givenUnmanagedObjects_whenInjectingIdService_thenIdValueIsCorrectlySet() { // existing statements PersonEntity personEntity = new PersonEntity("Baeldung"); assertEquals(2, personEntity.getId()); assertEquals("Baeldung", personEntity.getName()); }
6. Предостережения
Хотя доступ к компонентам Spring из неуправляемого объекта удобен, это часто не рекомендуется делать.
Проблема в том, что неуправляемые объекты, включая сущности, обычно являются частью модели предметной области. Эти объекты должны содержать данные только для повторного использования в различных службах.
Введение бобов в такие объекты может связать компоненты и объекты вместе, что затруднит обслуживание и улучшение приложения.
7. Заключение
В этом учебном пособии описан процесс введения пружинного компонента в неуправляемый объект. В нем также упоминалась проблема проектирования, связанная с внедрением зависимостей в объекты.
Код реализации можно найти на GitHub .