Spring: @Компонент против @Bean

Я понимаю, что в spring 2.5 была введена аннотация @Component, чтобы избавиться от определения xml bean, используя сканирование классов.

@Bean был введен в spring 3.0 и может использоваться с @Configuration, чтобы полностью избавиться от xml файла и использовать java-конфигурацию вместо этого.

Возможно ли повторное использование аннотации @Component вместо введения аннотации @Bean? Я понимаю, что конечной целью является создание beans в обоих случаях.

+334
источник поделиться
12 ответов

@Component и @Bean делают две совершенно разные вещи, и их не следует путать.

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

@Bean используется для явного объявления одного bean, а не для Spring делать это автоматически, как указано выше. Он отделяет объявление bean от определения класса и позволяет вам создавать и настраивать beans точно, как вы выбираете.

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

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

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

+343
источник

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

Когда вы должны использовать @Bean?

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

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

+269
источник
другие ответы

Связанные вопросы


Похожие вопросы

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

@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();
    }
}

Однако это невозможно сделать с помощью @Component.

+150
источник

Оба подхода нацелены на регистрацию целевого типа в контейнере Spring.

Разница в том, что @Bean применим к методам, тогда как @Component применим к типам.

Поэтому, когда вы используете аннотацию @Bean, вы управляете логикой создания экземпляра в теле метода (см. пример выше). С аннотацией @Component вы не можете.

+66
источник
  1. @Component автоматически обнаруживает и настраивает bean-компоненты, используя сканирование пути к классам, тогда как @Bean явно объявляет один bean-компонент, а не позволяет Spring делать это автоматически.
  2. @Component не отделяет объявление bean-компонента от определения класса, а @Bean отделяет объявление bean-компонента от определения класса.
  3. @Component - это аннотация уровня класса, где @Bean - это аннотация уровня метода, а имя метода служит именем компонента.
  4. @Component не нужно использовать с аннотацией @Configuration, где аннотация @Bean должна использоваться внутри класса, аннотируемого @Configuration.
  5. Мы не можем создать bean-компонент класса, используя @Component, если класс находится вне контейнера Spring, тогда как мы можем создать bean-компонент класса, используя @Bean, даже если класс присутствует вне контейнера Spring.
  6. @Component имеет различные специализации, такие как @Controller, @Repository и @Service, тогда как @Bean не имеет специализаций.
+55
источник

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

Если вы хотите узнать больше о @Component и других аннотациях стереотипа, рекомендуем взглянуть на эту статью.

@Bean используется для явного объявления и регистрации bean-компонента (в качестве bean-компонента конфигурации) в контейнере Spring IOC, который возвращается из метода. @Bean - это аннотация уровня метода, и она используется в классе, аннотированном @Configuration. Проще говоря, аннотация @Bean используется для регистрации компонента, возвращаемого методом, в качестве компонента конфигурации пружины в контейнере IOC. @Bean - это только аннотация уровня метода, и ее нельзя использовать с классами и объявлением объекта.

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

Чтобы объявить бин, просто аннотируйте метод аннотацией @Bean. Когда JavaConfig встречает такой метод, он выполняет этот метод и регистрирует возвращаемое значение как компонент в ApplicationContext. По умолчанию имя компонента будет таким же, как имя метода. Ниже приведен простой пример объявления метода @Bean.

@Configuration
public class ApplicationConfig {

    @Bean
    public User adminUserProfile() {
        return new User("Rami","Nassar");
    }
}

В классе ApplicationConfig вы можете видеть, что сначала мы используем аннотацию @Configuration, чтобы сообщить Spring, что это файл конфигурации на основе Java. После этого аннотация @Bean используется для объявления bean-компонента Spring и требований DI. Аннотация @Bean эквивалентна тэг, имя метода эквивалентно атрибуту id внутри тег. Я надеюсь, что после прочтения этой статьи вы получите четкое представление о реальной цели и использовании аннотаций @Bean и @Component.

+40
источник

Когда вы используете тег @Component, он аналогичен наличию POJO (Plain Old Java Object) с методом объявления ванильного компонента (с аннотацией @Bean). Например, следующий метод 1 и 2 даст тот же результат.

Способ 1

@Component
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

с бобом для 'theNumber':

@Bean
Integer theNumber(){
    return new Integer(3456);
}

Способ 2

//Note: no @Component tag
public class SomeClass {

    private int number;

    public SomeClass(Integer theNumber){
        this.number = theNumber.intValue();
    }

    public int getNumber(){
        return this.number;
    }
}

с бобами для обоих:

@Bean
Integer theNumber(){
    return new Integer(3456);
}

@Bean
SomeClass someClass(Integer theNumber){
    return new SomeClass(theNumber);
}

Метод 2 позволяет вам сохранять объявления bean-компонентов вместе, он немного более гибок и т.д. Вы можете даже захотеть добавить другой не-vanilla bean-компонент SomeClass, как показано ниже:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}
+14
источник
  • @component и его специализации (@Controller, @service, @repository) позволяют автоматически обнаруживать с помощью сканирования путей к классам. Если мы увидим класс компонента, такой как @Controller, @service, @repository будет автоматически сканироваться средой Spring с использованием сканирования компонента.
  • @Bean, с другой стороны, может использоваться только для явного объявления одного компонента в классе конфигурации.
  • @Bean раньше явно объявлял один бин, а не давал Spring делать это автоматически. Это делает отдельное объявление bean-компонента из определения класса.
  • Короче говоря, @Controller, @service, @repository предназначены для автоопределения, а @Bean - для создания отдельного компонента из класса.
    - @Controller
    public class LoginController 
    { --code-- }

    - @Configuration
    public class AppConfig {
    @Bean
    public SessionFactory sessionFactory() 
    {--code-- }
+5
источник

У вас есть два способа создания бобов. Одним из них является создание класса с аннотацией @Component. Другой - создать метод и аннотировать его с помощью @Bean. Те классы, которые содержат метод с @Bean должны быть аннотированы с помощью @Configuration После запуска проекта @ComponentScan класс с аннотацией @ComponentScan будет сканировать каждый класс с @Component и восстанавливать экземпляр этого класса в контейнере Ioc. Другая вещь, @ComponentScan должен сделать @ComponentScan, - это запуск методов с @Bean и восстановление возвращаемого объекта в контейнер Ioc в виде компонента. Поэтому, когда вам нужно решить, какой тип бобов вы хотите создать, в зависимости от текущих состояний, вам нужно использовать @Bean. Вы можете написать логику и вернуть нужный объект. Еще одна вещь, которую стоит упомянуть - это имя метода с @Bean - это имя по умолчанию для bean-компонента.

+5
источник

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

Более того, у вас есть полный контроль над тем, как создавать bean-компоненты, когда этого недостаточно для стандартной реализации Spring.

Я написал пост об этом.

https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/

+2
источник

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

  • @Bean

Сначала это аннотация уровня метода. Во-вторых, вы обычно используете для настройки bean-компонентов в java-коде (если вы не используете конфигурацию xml), а затем вызываете его из класса, используя метод getBean ApplicationContext. лайк

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

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Составная часть

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

Мы получаем что-то вроде этого.

@Component
class User {
}

//to get Bean
@Autowired
User user;

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

+2
источник

Вы можете использовать @Bean чтобы сделать существующий сторонний класс доступным для контекста приложения Spring Framework.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

    viewResolver.setPrefix("/WEB-INF/view/");
    viewResolver.setSuffix(".jsp");

    return viewResolver;
}

Используя аннотацию @Bean, вы можете обернуть сторонний класс (он может не иметь @Component и не может использовать Spring), как бин Spring. И затем, когда он обернут с помощью @Bean, он становится одноэлементным объектом и доступен в контексте приложения Spring Framework. Теперь вы можете легко поделиться/повторно использовать этот компонент в своем приложении, используя внедрение зависимостей и @Autowired.

Так что подумайте о аннотации @Bean - обертке/адаптере для сторонних классов. Вы хотите, чтобы сторонние классы были доступны для контекста приложения Spring Framework.

Используя @Bean в приведенном выше коде, я явно объявляю один компонент, потому что внутри метода я явно создаю объект, используя ключевое слово new. Я также вручную вызываю методы установки данного класса. Так что я могу изменить значение поля префикса. Так что эта ручная работа называется явным созданием. Если я использую @Component для того же класса, боб, зарегистрированный в контейнере Spring, будет иметь значение по умолчанию для поля префикса.

С другой стороны, когда мы аннотируем класс с помощью @Component, нам не нужно вручную использовать ключевое слово new. Он обрабатывается автоматически Spring.

+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос