Ответ
Не всегда. Ленивая инициализация (@Lazy) сохраняется только если и принимающий бин (клиент), и контекст внедрения настроены соответствующим образом. В противном случае Spring создаст зависимый бин во время создания бина-клиента.
Правила и сценарии:
-
Внедрение через конструктор (по умолчанию не ленивое): Если бин-клиент не является
@Lazy, Spring создаст ленивый бин-зависимость во время создания клиента, так как ему нужен готовый аргумент для конструктора.@Component class Client { private final Service service; // Service будет создан НЕМЕДЛЕННО при создании Client! public Client(@Lazy Service service) { this.service = service; } } -
Внедрение через поле или setter-метод: Ленивая зависимость будет создана только при первом обращении к полю/методу.
@Component class Client { @Autowired @Lazy // Прокси внедряется сразу, реальный объект Service создастся при первом вызове private Service service; } -
Полностью ленивая цепочка: Чтобы и клиент, и его зависимость инициализировались лениво, нужно аннотировать
@Lazyоба бина.@Configuration class AppConfig { @Bean @Lazy public Service service() { return new Service(); } @Bean @Lazy // Client и его зависимость Service создадутся только при первом обращении public Client client(Service service) { return new Client(service); } }
Ключевой вывод: Аннотация @Lazy создаёт прокси-объект. Момент инициализации реального объекта зависит от способа и контекста внедрения.
Ответ 18+ 🔞
Ну ты представляешь, эта ваша аннотация @Lazy — она как хитрая жопа, понимаешь? Не всегда она работает так, как ты думаешь. Она сохраняет свою ленивость только если и тот, кто её получает, и само место, куда её пихают, тоже на эту ленивую волну настроены. А иначе Spring возьмёт и создаст эту зависимость сразу, как будто никакой @Lazy и не было, вот тебе и сказка про Буратино, в рот меня чих-пых!
Смотри, как это работает, а то потом будешь охуевать, почему всё создалось не тогда, когда надо.
Первое, конструктор (по дефолту он не ленивый, жадный как собака):
Если твой бин-клиент сам не помечен как @Lazy, то Спринг, создавая его, упрётся в конструктор. Ему же нужен аргумент! И он, сука, создаст эту ленивую зависимость сразу, в момент создания клиента. Прокси тут не спасёт, потому что конструктору нужен реальный объект для передачи.
@Component
class Client {
private final Service service;
// Service будет создан НЕМЕДЛЕННО, блядь, при создании Client! Ленивость нахуй слетела.
public Client(@Lazy Service service) {
this.service = service;
}
}
Второе, поле или сеттер (тут уже интереснее):
А вот тут уже прокси отработает как надо. Внедрится какая-то заглушка, а реальный объект Service родится только в тот самый момент, когда ты к нему впервые обратишься. Как по маслу.
@Component
class Client {
@Autowired
@Lazy // Прокси внедряется сразу, а реальный Service вылезет только при первом вызове. Уже теплее.
private Service service;
}
И наконец, полная ленивая цепь (чтоб всё и всем было похуй):
Чтобы и клиент, и его зависимость инициализировались только когда их ткнут палкой, надо пометить @Lazy оба бина, ёпта! Тогда вся эта конструкция будет спать до последнего.
@Configuration
class AppConfig {
@Bean
@Lazy
public Service service() {
return new Service();
}
@Bean
@Lazy // И Client, и его зависимость Service создадутся только при первом обращении. Идеальная лень!
public Client client(Service service) {
return new Client(service);
}
}
Короче, вывод, блядь, ключевой: Аннотация @Lazy — это не волшебная палочка, а генератор прокси. А вот когда этот прокси превратится в реальный объект — это уже зависит от того, куда и как ты его засунул. Так что думай, бошка, куда аннотации лепишь, а то получишь инициализацию не тогда, когда хотел.