JavaRush /Курсы /Spring /ApplicationContextAware и BeanNameAware

ApplicationContextAware и BeanNameAware

Spring
1 уровень , 22 лекция
Открыта

Если ApplicationContext создает экземпляр объекта, реализующий интерфейс org.springframework.context.ApplicationContextAware, экземпляру предоставляется ссылка на этот ApplicationContext. В следующем листинге показано определение интерфейса ApplicationContextAware:

public interface ApplicationContextAware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

Таким образом, бины могут программно манипулировать создавшим их ApplicationContext через интерфейс ApplicationContext или путем приведения ссылки на известный подкласс этого интерфейса (например, ConfigurableApplicationContext, который открывает дополнительную функциональность). Одним из вариантов использования может быть программное получение других бинов. Иногда эта возможность бывает полезной. Однако, в целом, вам следует избегать этого, поскольку способ связывает код со Spring и не следует стилю инверсии управления, при котором взаимодействующие объекты предоставляются бинам в качестве свойств. Другие методы ApplicationContext обеспечивают доступ к файловым ресурсам, возможность публикации событий приложения и доступ к MessageSource. Эти дополнительные возможности описаны в Дополнительные возможности ApplicationContext.

Другой альтернативой получения ссылки на ApplicationContext является автоматическое обнаружение и связывание. Традиционные режимы автоматического обнаружения и связывания constructor и byType могут предоставлять зависимость типа ApplicationContext для аргумента конструктора или параметра устанавливающего метода, соответственно. Для большей гибкости, включая возможность автоматического обнаружения и связывания полей и методов с несколькими параметрами, используйте функции автоматического обнаружения и связывания на основе аннотаций. В этом случае для ApplicationContext производится автоматическое обнаружение и связывание с полем, аргументом конструктора или параметром метода, которые принимают тип ApplicationContext, если поле, конструктор или метод содержат аннотацию @Autowired.

Если ApplicationContext создает класс, реализующий интерфейс org.springframework.beans.factory.BeanNameAware, класс получает ссылку на имя, определенное в связанном с ним определении объекта. В следующем листинге показано определение интерфейса BeanNameAware:

public interface BeanNameAware {
    void setBeanName(String name) throws BeansException;
}

Обратный вызов инициируется после заполнения обычных свойств бина, но до обратного вызова инициализации, например InitializingBean.afterPropertiesSet() или специального init-метода.

Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Камушек Уровень 36
6 марта 2024
Проблема зависимости бинов с разными scope. Возможна ситуация, когда один бин зависит от другого, при этом у них разные жизненные циклы. На пример singleton бин CommandManager зависит от prototype бина Command. (Более расширенный scope зависит от менее расширенного scope) CommandManager создается один раз, и хранит в себе ссылку на бин Command , который должен создаваться каждый раз новый. Для этого: 1. имплементируемся от ApplicationContextAware. 2. реализуем его единственный метод

void setApplicationContext (ApplicationContext applicationContext) throws BeansException{
this.applicationContext = applicationContext;
}
3. используем локальный applicationContext в методе, где необходимо возвращать прототип:

protected Command createCommand(){
return this.applicationContext.getBean( "command", Command.class);
} 
- имя можно не использовать, достаточно указать тип.
Камушек Уровень 36
6 марта 2024
это один из примеров решения проблемы зависимости бинов с разными scope, но в данном случае происходит жесткое связывание со спрингом, и нарушается принцип единственной ответственности, суть данного примера показать, каким образом можно получить прототип. Но лучше использовать @Lookup.

@Component
@Scope("prototype")
class Passenger {
privat String name;
//определены get и set 
}

@Component
class Car{
@Lookup 
public Passenger createPassenger(){
return null;
}

public String drive(String name)[
Passenger pas = createPassenger();
pas.setName(name);
return "Car with" + pas.getName();
}
Суть в том, что мы создаем метод-заглушку в бине Car и помечаете его специальным образом – аннотацией @Lookup. Этот метод должен возвращать бин Passenger, каждый раз новый. Контейнер Spring под капотом создаст прокси и переопределит этот метод и будет вам выдавать новый экземпляр бина Passenger при каждом вызове аннотированного метода. Даже если в вашей заглушке он возвращает null.