Весна: @ Компонент проти @Bean


459

Я розумію, що @Componentанотація була введена навесні 2.5, щоб позбутися визначення xml-квасолі за допомогою сканування classpath.

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

Чи можна було б повторно використовувати @Componentанотацію замість введення @Beanанотації? Я розумію, що кінцевою метою є створення бобів в обох випадках.


4
Чи є де-небудь @Bean можна використовувати крім класу Configuration?
— Вілла


@Willa Так, є. Так називається Lite mode. І не рекомендується. Дивіться тут: docs.spring.io/spring/docs/current/spring-framework-reference/…
— smwikipedia

8
Я підсумував би це, говорячи про метод із @beanповерненням настроюваного екземпляра весняного боба, в той час як @componentвизначає клас, який може бути інстанційований пізніше IoC двигуном при необхідності.
— Себара

Відповіді:


433

@Componentі @Beanробити дві досить різні речі, і їх не слід плутати.

@Component(і @Serviceта @Repository) використовуються для автоматичного виявлення та автоматичної конфігурації бобів за допомогою сканування класових шляхів. Існує неявне відображення "один на один" між анотованим класом і біном (тобто один квасоля на клас). Контроль електропроводки досить обмежений при такому підході, оскільки це суто декларативно.

@Beanвикористовується для явного оголошення єдиного бобу, а не для того, щоб дозволити Spring робити це автоматично, як зазначено вище. Він відокремлює декларацію квасолі від визначення класу і дозволяє створювати та налаштовувати боби саме так, як ви вибрали.

Щоб відповісти на ваше запитання ...

чи можна було б повторно використовувати @Componentанотацію замість введення @Beanанотації?

Звичайно, певно; але вони вирішили цього не робити, оскільки вони дуже різні. Весна вже досить заплутана, не забруднюючи далі води.


3
Тож я можу користуватися лише @Componentтоді, коли потрібен автопровід? Здається, це @Beanніяк не може вплинути@Autowired
— Jaskey

3
використовуйте "@компонент" для класів, що базуються на сервісах, "@Bean" як більш фабрично виготовлені об'єкти, наприклад, jdbc джерело даних
— Junchen Liu

2
@Jaskey ви можете використовувати @Autowiredз , @Beanякщо ви анотований свій клас компонента з@Configuration
— starcorn

6
Вибачте, але я не можу зрозуміти слово вашого пояснення. Ви чітко це розумієте, тому, будь ласка, напишіть чітке пояснення чи вкажете відповідну документацію?
— Alex Worden

13
Тепер, коли я розумію концепцію (з читання відповідей інших людей), ваше пояснення має сенс. Що ще більше підказує мені, що ваше пояснення не корисне для тих, хто вже не розуміє понять.
— Alex Worden

397

@ Компонент Переважно для сканування компонентів та автоматичного проводки.

Коли слід використовувати @Bean ?

Іноді автоматична конфігурація - це не варіант. Коли? Давайте уявимо, що ви хочете з'єднати компоненти з сторонніх бібліотек (у вас немає вихідного коду, щоб ви не могли коментувати його класи за допомогою @Component), тому автоматична конфігурація неможлива.

@Bean анотацію повертає об'єкт , який пружина повинна реєструватися в якості бобу в контексті програми. Тіло методу несе логіку , відповідальний за створення екземпляра.


5
Я думаю, що це має найбільше значення. Якщо я правильно розумію, @Componentпереходить до самих класів, тоді як @Beanпереходить до методів класу (які дають екземпляри об’єктів класу).
— jocull

182

Розглянемо, що я хочу конкретної реалізації залежно від динамічного стану. @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.


3
Як ви називаєте цей приклад класу?
— PowerFlower

1
@PowerFlower Цей метод повинен бути в класі конфігурації, в якому @Configuration
— зазначається

97

Обидва підходи спрямовані на реєстрацію цільового типу у контейнері Spring.

Різниця в тому, що @Beanзастосовна до методів , тоді @Componentяк стосується типів .

Тому, використовуючи @Beanпримітку, ви керуєте логікою створення екземпляра в тілі методу (див. Приклад вище ). З @Componentанотацією ви не можете.


Що таке тип?
— Jac Frall

97
  1. @Component автоматично виявляє та конфігурує квасоля за допомогою сканування класовим шляхом, тоді як @Bean явно оголошує єдиний боб, а не дозволяє Spring робити це автоматично.
  2. @Component не відокремлює декларацію квасолі від визначення класу, де як @Bean відокремлює декларацію квасолі від визначення класу.
  3. @Component - це анотація на рівні класу, тоді як @Bean - анотація на рівні методу, а ім'я методу служить ім'ям боба.
  4. @Component не потрібно використовувати з анотацією @Configuration, де анотація @Bean повинна використовуватися в класі, який позначається за допомогою @Configuration .
  5. Ми не можемо створити боб класу за допомогою @Component, якщо клас знаходиться поза весняним контейнером, тоді як ми можемо створити боб класу за допомогою @Bean, навіть якщо клас присутній поза контейнером весни .
  6. @Component має різні спеціалізації, такі як @Controller, @Repository та @Service, тоді як @Bean не має спеціалізацій .

3
4. Насправді @Bean можна було оголосити в неконфігураційному класі. Він відомий як Lite mode
— voipp

1
Щодо пункту 5. Я думаю, що ми помістили боби всередину пружинної ємності. Отже, кожен клас знаходиться поза весняним контейнером. Я думаю, пункт 5 повинен бути винагороджений
— Eugen

20

Я бачу багато відповідей, і майже скрізь його згаданий @Component призначений для автоматичного з'єднання, де сканується компонент, а @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;

Це воно . Він був просто введений, щоб уникнути всіх кроків конфігурації для створення екземпляра та використання цього компонента.


5
Я думаю, що не потрібно отримувати об’єкт User з ApplicationContext, коли ви використовуєте @Beanпідхід. Ви все ще можете використовувати @Autowireдля отримання квасолі, як ви це зробили б у випадку @Component. @Beanпросто додає квасоля до весняного контейнера так само, як це @Componentробиться. Різниця полягає в наступному. 1. Використовуючи @Bean, ви можете додавати сторони класів до весняного контейнера. 2. Використовуючи @Bean, ви можете отримати бажану реалізацію інтерфейсу під час виконання (Використовуючи заводський шаблон дизайну)
— Енді

20

Ви можете використовувати @Beanнаявний сторонній клас доступним для контексту програми Spring Spring.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

Використовуючи @Beanанотацію, ви можете обгортати сторонній клас (він може не мати @Componentта може не використовувати Spring), як весняний боб. А потім, коли він завершується з використанням @Bean, він стає об'єктом одиночної форми і доступний у контексті програми Spring Framework. Тепер ви можете легко ділитися / використовувати цей боб у вашому додатку, використовуючи введення залежності та @Autowired.

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

Використовуючи @Beanв наведеному вище коді, я явно оголошую один боб, оскільки всередині методу я явно створюю об'єкт за допомогою newключового слова. Я також вручну викликаю методи встановлення даного класу. Тому я можу змінити значення поля префікса. Тож ця ручна робота називається явним створенням. Якщо я використовую @Componentдля того ж класу, bean, зареєстрований у контейнері Spring, матиме значення за замовчуванням для поля префікса.

З іншого боку, коли ми коментуємо клас @Component, не потрібно вручну використовувати newключове слово. Він обробляється автоматично Spring.


1
Було б добре, якби ця відповідь була доповнена прикладом того, як використовується і цей квасоля
— softarn

Як би ви обернули @Bean над стороннім класом, якщо вихідний код не дозволяє змінювати?
— veritas

16

Якщо ви використовуєте @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;
    }
}

з квасолею для "числа":

@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 дозволяє зберігати декларації квасолі разом, це трохи гнучкіше і т. Д. Ви можете навіть додати ще одну квасолю не-ванільного SomeClass на зразок наступного:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}

10

У вас є два способи отримання бобів. Перший - створити клас з анотацією @Component. Інше - створити метод та анотувати його @Bean. Для тих класів, що містять метод с . Ви можете написати логіку і повернути потрібний об’єкт. Інша річ, яку варто згадати - це ім'я методу , за замовчуванням назва bean.@Bean слід позначати: @Configuration Після запуску весняного проекту, клас із @ComponentScanприміткою просканує кожен клас із @Componentним та відновить екземпляр цього класу до контейнера Ioc. Інша справа, це @ComponentScanзробити це запустити методи з @Beanним і відновити об'єкт, що повертається, в контейнер Ioc як боб. Отже, коли вам потрібно вирішити, який вид квасолі ви хочете створити, залежно від поточних станів, вам потрібно скористатися@Bean@Bean


6
  • @компонент та його спеціалізації (@Controller, @service, @repository) дозволяють здійснювати автоматичне виявлення за допомогою сканування класного шляху. Якщо ми побачимо клас компонентів, наприклад @Controller, @service, @repository, автоматично сканується весняною рамкою за допомогою сканування компонентів.
  • @Bean, з іншого боку, може використовуватися лише для явного оголошення одного квасолі в класі конфігурації.
  • @Bean використовував, щоб явно оголосити один боб, а не дозволяти весни робити це автоматично. Її складають декларацію про квасолі з визначення класу.
  • Коротше кажучи, @Controller, @service, @repository призначені для автоматичного виявлення та @Bean для створення роздільної квасолі з класу
    - @Controller
    публічний клас LoginController 
    {--код--}

    - @Configuration
    публічний клас AppConfig {
    @Bean
    публічна сесіяФакторна сесіяФакторна () 
    {--код--}

3

@Bean був створений, щоб уникнути з'єднання Весни та правил вашого бізнесу під час компіляції. Це означає, що ви можете повторно використовувати свої бізнес-правила в інших рамках, таких як PlayFramework або JEE.

Більше того, у вас є повний контроль над тим, як створювати квасоля, де недостатньо весняних інстанцій за замовчуванням.

Я написав пост, в якому говорив про це.

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



1

1. Про @Component
@Component функціонує аналогічно @Configuration.

Вони обоє вказують на те, що в анотованому класі є одна або кілька бобів, які потрібно зареєструвати Spring-IOC-Container.

Клас, який позначає @Component, ми називаємо його Component of Spring. Це поняття, яке містить кілька бобів.

Component classДля автоматичної реєстрації цих бобів потрібно провести Spring скануванням component class.

2. Про @Bean
@Bean використовується для анотації методу component-class(як зазначено вище). Він вказує на те, що слід реєструвати примірник, переглянутий за допомогою анотованого методу Spring-IOC-Container.

3. Висновок
Різниця між ними двома відносно очевидна, вони використовуються в different circumstances. Загальне використання:

    // @Configuration is implemented by @Component
    @Configuration
    public ComponentClass {

      @Bean
      public FirstBean FirstBeanMethod() {
        return new FirstBean();
      }

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }

0

Додаткові бали відповіді вище

Скажімо, у нас з'явився модуль, який спільно використовується у декількох додатках, і він містить кілька служб. Не всі потрібні для кожного додатка.

Якщо використовувати @Component для цих класів обслуговування та сканування компонентів у додатку,

ми можемо виявити більше бобів, ніж потрібно

У цьому випадку вам або довелося налаштувати фільтрування сканування компонентів або забезпечити конфігурацію, що навіть невикористані боби можуть працювати. В іншому випадку контекст програми не запуститься.

У цьому випадку краще працювати з анотацією @Bean і лише інстанціювати ці боби,

які потрібні індивідуально у кожному додатку

Отже, по суті, використовуйте @Bean для додавання сторонніх класів у контекст. І @Component, якщо він знаходиться просто у вашій одній програмі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.