Работа аннотации @Bean в Spring: один или несколько объектов?

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для обеспечения использования singleton-экземпляра бина достаточно обратиться к методу с аннотацией @Bean в конфигурационном классе Spring. Это даст возможность многократно вызывать уже созданные бины, поддерживая их уникальность в контексте приложения.

Java
Скопировать код
@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }

    // Многократное использование экземпляра MyBean как singleton
    public void someMethod() {
        MyBean bean = myBean();
    }
}

Учтите, что прямое обращение к методам соответствует принципам внедрения зависимостей и жизненного цикла в Spring, что позволяет избежать ненужного клонирования объектов.

Если вам необходимо при каждом обращении получать новый экземпляр бина, укажите область видимости "prototype" с помощью аннотации @Scope("prototype") в методе @Bean.

Java
Скопировать код
@Bean
@Scope("prototype")
public MyBean prototypeBean() {
    return new MyBean();
}

Для методов, которым необходимо избежать проксирование, используйте статические методы с аннотацией @Bean. Это обеспечивает прямое создание экземпляров.

Java
Скопировать код
@Bean
public static MyBean alwaysNewBean() {
    return new MyBean();
}
Кинга Идем в IT: пошаговый план для смены профессии

Основы проксирования с CGLIB

CGLIB преобразует @Bean-методы таким образом, чтобы они создавали singleton-экземпляры. Однако это не относится к статическим методам.

Java
Скопировать код
@Configuration
public class ProxyConfig {

    @Bean
    public Service service() {
        return new ServiceImpl();
    }

    public Service createService() {
        return service(); // Синглтон и проксирование CGLIB в действии!
    }
    
    public static Service createNewService() {
        return service(); // Не будет скомпилировано; статические методы не допускают проксирование!
    }
}

Непредсказуемые ситуации: сложные паттерны

В случаях сложной инициализационной логики может потребоваться создание нового экземпляра. В этих ситуациях рекомендуется использовать внедрение зависимостей либо метод getBean() для доступа к бинам с областью видимости "prototype".

При вызове метода @Bean внутри класса Spring ведет учёт, однако, если нужно обратиться к этому же методу "извне", следует использовать контекст приложения для получения бина.

Java
Скопировать код
@Configuration
public class ExternalConfig {

    @Autowired
    private ApplicationContext context;

    public void useBean() {
        MyBean bean = context.getBean(MyBean.class); // Корректный вызов singleton-бина
    }
}

Визуализация

Представим себе садовника, выбирающего растения из питомника:

Markdown
Скопировать код
👩‍🌾: "Мне нужен подсолнух 🌻 из моего питомника для устройства переднего двора."

Теперь сравним это с вызовом метода @Bean в Spring:

Java
Скопировать код
@Bean
public Sunflower sunflower() {
    return new Sunflower();
}
Markdown
Скопировать код
Сад (🏡): [🌹, 🌷, 🌻, 🌼]

Как и Spring, садовник на организованный манер при каждой необходимости запрашивает новые экземпляры растений.

Оживление вашей конфигурации

Методы с аннотацией @Bean могут быть объявлены как защищённые, приватные или пакетные, хотя для улучшения читаемости кода рекомендуются публичные. В этих методах использование рефлексии может стать источником проблем из-за ограничений безопасности JVM.

Зная нюансы работы с singleton-областью видимости и аннотацией @Bean, вы сможете применять различные паттерны проектирования, создавая чистый и легко поддерживаемый код.

Полезные материалы

  1. Понимание аннотации Spring @Bean — подробный разбор в официальной документации Spring.
  2. Spring – Конфигурация на Java — глобальный обзор создания бинов в Spring с использованием @Bean.
  3. Справочная документация Spring Boot — инструкция по использованию @Bean в Spring Boot.
  4. java – Как получить экземпляр класса типа T? – Stack Overflow — обсуждение на StackOverflow о прямых вызовах @Bean.
  5. Аннотации Spring | DigitalOcean — понятное руководство по использованию аннотаций Spring.