Весна: @ Компонент проти @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.