«1. Обзор

В этом кратком руководстве мы сосредоточимся на интерфейсах BeanNameAware и BeanFactoryAware в Spring Framework.

Мы опишем каждый интерфейс отдельно с плюсами и минусами их использования.

2. Интерфейс Aware

И BeanNameAware, и BeanFactoryAware принадлежат интерфейсу корневого маркера org.springframework.beans.factory.Aware. Это использует инъекцию сеттера для получения объекта во время запуска контекста приложения.

Интерфейс Aware представляет собой смесь шаблонов обратного вызова, слушателя и наблюдателя. Это указывает на то, что bean-компонент может быть уведомлен контейнером Spring с помощью методов обратного вызова.

3. BeanNameAware

BeanNameAware сообщает объекту имя компонента, определенное в контейнере.

Давайте рассмотрим пример:

public class MyBeanName implements BeanNameAware {

    @Override
    public void setBeanName(String beanName) {
        System.out.println(beanName);
    }
}

Свойство beanName представляет идентификатор компонента, зарегистрированный в контейнере Spring. В нашей реализации мы просто отображаем имя компонента.

Далее давайте зарегистрируем bean-компонент этого типа в классе конфигурации Spring:

@Configuration
public class Config {

    @Bean(name = "myCustomBeanName")
    public MyBeanName getMyBeanName() {
        return new MyBeanName();
    }
}

Здесь мы явно присвоили имя нашему классу MyBeanName с помощью строки @Bean(name = «myCustomBeanName»).

Теперь мы можем запустить контекст приложения и получить из него бин:

AnnotationConfigApplicationContext context 
  = new AnnotationConfigApplicationContext(Config.class);

MyBeanName myBeanName = context.getBean(MyBeanName.class);

Как мы и ожидали, метод setBeanName выводит «myCustomBeanName».

Если мы удалим код name = “…†из аннотации @Bean, контейнер в этом случае присвоит имя метода getMyBeanName() компоненту. Таким образом, вывод будет «getMyBeanName».

4. BeanFactoryAware

BeanFactoryAware используется для внедрения объекта BeanFactory. Таким образом мы получаем доступ к BeanFactory, которая создала объект.

Вот пример класса MyBeanFactory:

public class MyBeanFactory implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public void getMyBeanName() {
        MyBeanName myBeanName = beanFactory.getBean(MyBeanName.class);
        System.out.println(beanFactory.isSingleton("myCustomBeanName"));
    }
}

С помощью метода setBeanFactory() мы присваиваем ссылку BeanFactory из контейнера IoC свойству beanFactory.

После этого мы можем использовать его напрямую, как в функции getMyBeanName().

Давайте инициализируем MyBeanFactory и вызовем метод getMyBeanName():

MyBeanFactory myBeanFactory = context.getBean(MyBeanFactory.class);
myBeanFactory.getMyBeanName();

Поскольку мы уже создали экземпляр класса MyBeanName в предыдущем примере, Spring вызовет здесь существующий экземпляр.

Строка beanFactory.isSingleton(“myCustomBeanName”) подтверждает это.

5. Когда использовать?

Типичным вариантом использования BeanNameAware может быть получение имени компонента для регистрации или подключения. Для BeanFactoryAware это может быть возможность использовать Spring bean из устаревшего кода.

В большинстве случаев нам следует избегать использования каких-либо интерфейсов Aware, если они нам не нужны. Реализация этих интерфейсов свяжет код с инфраструктурой Spring.

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

В этой статье мы узнали об интерфейсах BeanNameAware и BeanFactoryAware и о том, как их использовать на практике.

Как обычно, полный код этой статьи доступен на GitHub.