7

Spring: @Component против @Bean

3

Я понимаю, что аннотация @Component была введена в Spring 2.5 для того, чтобы избавиться от определения бинов в XML, используя сканирование классов. Аннотация @Bean была представлена в Spring 3.0 и может использоваться вместе с @Configuration, позволяя полностью отказаться от XML-файлов и использовать конфигурацию на Java.

Могло ли быть возможно повторное использование аннотации @Component вместо введения аннотации @Bean? Мое понимание заключается в том, что в обоих случаях конечная цель — создание бинов.

5 ответ(ов)

7

@Component Предпочтительно использовать для сканирования компонентов и автоматического связывания.

Когда следует использовать @Bean?

Иногда автоматическая конфигурация невозможна. Когда именно? Представьте себе ситуацию, когда вам нужно подключить компоненты из сторонних библиотек (у вас нет исходного кода, поэтому вы не можете аннотировать их классы с помощью @Component), и, следовательно, автоматическая конфигурация не осуществляется.

Аннотация @Bean возвращает объект, который Spring должен зарегистрировать как бин в контексте приложения. Тело метода содержит логику, отвечающую за создание экземпляра.

5

@Component и @Bean выполняют достаточно разные функции и не должны путаться.

Аннотация @Component (а также @Service и @Repository) используется для автоматического обнаружения и конфигурации бинов с помощью сканирования класса. Существует неявное сопоставление один-к-одному между аннотированным классом и бином (то есть один бин на класс). Контроль за связыванием довольно ограничен, так как это чисто декларативный подход.

Аннотация @Bean используется для явного объявления одного бина, вместо того чтобы позволять Spring делать это автоматически, как в случае с @Component. Она разделяет декларацию бина и определение класса, позволяя вам создавать и настраивать бины именно так, как вы хотите.

Чтобы ответить на ваш вопрос...

было ли бы возможно использовать аннотацию @Component вместо введения аннотации @Bean?

Конечно, вероятно, это было бы возможно; но они выбрали не делать этого, поскольку эти две аннотации существенно различаются. Spring и без того достаточно запутан, чтобы еще больше усложнять ситуацию.

2
  1. Аннотация @Component автоматически обнаруживает и настраивает бины с помощью сканирования classpath, в то время как аннотация @Bean явно объявляет один бин, не позволяя Spring делать это автоматически.

  2. Аннотация @Component не отделяет декларацию бина от определения класса, тогда как аннотация @Bean отделяет декларацию бина от определения класса.

  3. Аннотация @Component является аннотацией уровня класса, в то время как @Bean — это аннотация уровня метода, и имя метода служит именем бина.

  4. Аннотацию @Component не обязательно использовать с аннотацией @Configuration, тогда как аннотацию @Bean необходимо использовать внутри класса, аннотированного @Configuration.

  5. Мы не можем создать бин класса с помощью @Component, если класс находится вне контейнера Spring, в то время как мы можем создать бин класса с помощью @Bean, даже если класс находится вне контейнера Spring.

  6. Аннотация @Component имеет разные специализации, такие как @Controller, @Repository и @Service, в то время как у аннотации @Bean нет специализаций.

2

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

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

@Bean
@Scope("prototype")
public SomeService someService() {
    switch (state) {
        case 1:
            return new Impl1();
        case 2:
            return new Impl2();
        case 3:
            return new Impl3();
        default:
            return new Impl();
    }
}

В этом примере метод someService() возвращает разные реализации интерфейса SomeService в зависимости от значения переменной state. Каждый раз, когда вы запрашиваете бин, будет создаваться новый экземпляр SomeService, который соответствует текущему состоянию.

Однако, если вы попытаетесь сделать что-то подобное с аннотацией @Component, то столкнетесь с ограничениями. Аннотация @Component предназначена для подключения классов к контексту Spring без необходимости явного определения бинов. Но в этом случае Spring не предоставляет возможности динамического выбора реализации, так как бины, аннотированные @Component, по умолчанию являются одиночными (singleton) и не могут изменять свое состояние после создания.

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

0

Вижу много ответов, и почти во всех упоминается, что @Component используется для автозаполнения, где компонент сканируется, а @Bean ровно для того, чтобы объявить, что этот бин будет использоваться иначе. Позвольте показать, как это отличается.

  • @Bean

Во-первых, это аннотация на уровне метода. Во-вторых, вы обычно используете её для конфигурации бинов в Java-коде (если вы не используете XML-конфигурацию) и затем получаете её из класса с помощью метода ApplicationContext.getBean. Пример:

@Configuration
class MyConfiguration{
    @Bean
    public User getUser() {
        return new User();
    }
}

class User{
}    
        
// Получаем бин
User user = applicationContext.getBean("getUser");
  • @Component

Это общее способ аннотирования бина, а не специализированного бина. Это аннотация на уровне класса и используется для того, чтобы избежать всей этой конфигурационной работы через Java или XML.

Получается что-то вроде этого:

@Component
class User {
}

// чтобы получить бин
@Autowired
User user;

Вот и всё. Она была введена, чтобы избежать всех этапов конфигурации для инстанцирования и использования этого бина.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь