11. Расскажите про аннотацию @Lookup

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. Можно ли вставить бин в статическое поле? Почему?

Все вопросы по теме: список

Все темы: список

Вопросы/замечания/предложения/нашли ошибку: напишите мне

Report Page