Рубрики
Без рубрики

Инъекция яровых бобов в Неуправляемые объекты

Узнайте, как ввести пружинный боб в обычный объект.

Автор оригинала: 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 .