Сохраняется ли ленивая инициализация бина с аннотацией @Lazy в Spring, если он внедряется в другой бин?

Ответ

Не всегда. Ленивая инициализация (@Lazy) сохраняется только если и принимающий бин (клиент), и контекст внедрения настроены соответствующим образом. В противном случае Spring создаст зависимый бин во время создания бина-клиента.

Правила и сценарии:

  1. Внедрение через конструктор (по умолчанию не ленивое): Если бин-клиент не является @Lazy, Spring создаст ленивый бин-зависимость во время создания клиента, так как ему нужен готовый аргумент для конструктора.

    @Component
    class Client {
        private final Service service;
        // Service будет создан НЕМЕДЛЕННО при создании Client!
        public Client(@Lazy Service service) { 
            this.service = service;
        }
    }
  2. Внедрение через поле или setter-метод: Ленивая зависимость будет создана только при первом обращении к полю/методу.

    @Component
    class Client {
        @Autowired
        @Lazy // Прокси внедряется сразу, реальный объект Service создастся при первом вызове
        private Service service;
    }
  3. Полностью ленивая цепочка: Чтобы и клиент, и его зависимость инициализировались лениво, нужно аннотировать @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 — это не волшебная палочка, а генератор прокси. А вот когда этот прокси превратится в реальный объект — это уже зависит от того, куда и как ты его засунул. Так что думай, бошка, куда аннотации лепишь, а то получишь инициализацию не тогда, когда хотел.