11. Расскажите про аннотацию @Lookup
UNKNOWNОбычно бины в приложении Spring являтся синглтонами, и для внедрения зависимостей мы используем конструктор или сеттер.
Но бывает и другая ситуация: имеется бин Car – синглтон (singleton bean), и ему требуется каждый раз новый экземпляр бина Passenger. То есть Car – синглтон, а Passenger – так называемый прототипный бин (prototype bean). Жизненные циклы бинов разные. Бин Car создается контейнером только раз, а бин Passenger создается каждый раз новый – допустим, это происходит каждый раз при вызове какого-то метода бина Car. Вот здесь-то и пригодится внедрение бина с помощью Lookup-метода. Оно происходит не при инициализации контейнера, а позднее: каждый раз, когда вызывается метод.
Суть в том, что мы создаём метод-заглушку в бине Car и помечаем его специальным образом – аннотацией @Lookup. Этот метод должен возвращать бин Passenger, каждый раз новый. Контейнер Spring под капотом создаст прокси-подкласс и переопределит этот метод и будет нам выдавать новый экземпляр бина Passenger при каждом вызове аннотированного метода. Даже если в нашей заглушке он возвращает null (а так и надо делать - всё равно этот метод будет переопределен в прокси-подклассе):
@Component
public class Car {
@Lookup
public Passenger createPassenger() {
return null;
}
public String drive(String name) {
Passenger passenger = createPassenger();
passenger.setName(name);
return "car with " + passenger.getName();
}
}
Допустим, в бине есть метод drive(), и при каждом вызове метода drive() бину Car требуется новый экземпляр бина Passenger – сегодня пассажир Петя, завтра – Вася. То есть бин Passenger прототипный. Для получения этого бина надо написать метод-заглушку createPassenger() и аннотировать его с помощью @Lookup.
Контейнер Spring переопределит этот метод-заглушку и будет выдавать при его вызове каждый раз новый экземпляр Passenger.
Осталось только определить бин Passenger как прототипный:
@Component
@Scope("prototype")
public class Passenger {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Теперь при вызове метода drive() мы можем везти каждый раз нового пассажира. Имя его передаётся в аргументе метода drive(), и затем задается сеттером во вновь созданном экземпляре пассажира.
Предыдущий вопрос: 10. Расскажите про аннотацию @Inject
Следующий вопрос: 12. Можно ли вставить бин в статическое поле? Почему?
Все вопросы по теме: список
Все темы: список
Вопросы/замечания/предложения/нашли ошибку: напишите мне