Wiosna: @Component kontra @Bean

459

Rozumiem, że @Component adnotacja została wprowadzona wiosną 2.5 w celu pozbycia się definicji fasoli xml przy użyciu skanowania ścieżki klas.

@Bean został wprowadzony wiosną 3.0 i można go używać z @Configuration , aby w pełni pozbyć się pliku xml i zamiast tego użyć konfiguracji java.

Czy byłoby możliwe ponowne wykorzystanie @Componentadnotacji zamiast wprowadzania @Beanadnotacji? Rozumiem, że ostatecznym celem jest stworzenie fasoli w obu przypadkach.

użytkownik1396576
źródło
4
Czy istnieje gdzieś @Bean oprócz klasy Configuration?
Willa
@Willa Tak, jest. To się nazywa Lite mode. I nie jest to zalecane. Zobacz tutaj: docs.spring.io/spring/docs/current/spring-framework-reference/…
smwikipedia
8
Podsumowując, powiedziałbym, że metoda @beanzwraca zwracaną konfigurowalną instancję Spring Bean, a jednocześnie @componentdefiniuje klasę, która może być później zainicjowana przez wiosenny silnik IoC w razie potrzeby.
Sebas

Odpowiedzi:

433

@Componenti @Beanzrobić dwie zupełnie różne rzeczy i nie należy ich mylić.

@Component(i @Servicei @Repository) są używane do automatycznego wykrywania i automatycznej konfiguracji komponentów bean za pomocą skanowania ścieżki klas. Istnieje niejawne odwzorowanie jeden-do-jednego między klasą z adnotacjami a komponentem bean (tj. Jedna komponent bean na klasę). Kontrola okablowania jest dość ograniczona dzięki temu podejściu, ponieważ jest czysto deklaratywna.

@Beansłuży do jawnego zadeklarowania pojedynczej fasoli, zamiast pozwalać Springowi robić to automatycznie, jak wyżej. Oddziela deklarację fasoli od definicji klasy i pozwala tworzyć i konfigurować fasole dokładnie tak, jak wybierzesz.

Odpowiedzieć na Twoje pytanie...

czy byłoby możliwe ponowne wykorzystanie @Componentadnotacji zamiast wprowadzania @Beanadnotacji?

Pewnie, pewnie; ale postanowili tego nie robić, ponieważ te dwie rzeczy są zupełnie inne. Wiosna jest już dość myląca, nie powodując dalszego mętnienia wód.

skaffman
źródło
3
Czy mogę używać tylko @Componentwtedy, gdy potrzebny jest autowired? Wydaje się, że @Beannie ma to wpływu@Autowired
Jaskey,
3
użyj „@component” dla klas opartych na usługach, „@Bean” jako fabryka bardziej dostosowanych obiektów, np. źródło danych jdbc
Junchen Liu
2
@Jaskey można korzystać @Autowiredze @Beanjeśli opatrzone swoją klasę z fasoli@Configuration
starcorn
6
Przepraszam, ale nie rozumiem słowa twojego wyjaśnienia. Wyraźnie to rozumiesz, więc czy mógłbyś napisać jasne wyjaśnienie lub wskazać odpowiednią dokumentację?
Alex Worden,
13
Teraz, kiedy rozumiem pojęcie (z czytania odpowiedzi innych osób), twoje wyjaśnienie ma sens. Co mówi mi tym bardziej, że twoje wyjaśnienie nie jest dobre dla każdego, kto jeszcze nie rozumie pojęć.
Alex Worden,
397

@ Komponent Preferowany do skanowania komponentów i automatycznego okablowania.

Kiedy należy używać @Bean ?

Czasami automatyczna konfiguracja nie jest opcją. Kiedy? Wyobraźmy sobie, że chcesz połączyć komponenty z bibliotek stron trzecich (nie masz kodu źródłowego, więc nie możesz dodawać adnotacji do jego klas za pomocą @Component), więc automatyczna konfiguracja nie jest możliwa.

@Bean adnotacja zwraca obiekt , że wiosna powinna zarejestrować się jako fasoli w kontekście aplikacji. Treść metody zawiera logikę odpowiedzialną za utworzenie instancji.

MagGGG
źródło
5
Myślę, że to ma sens. Jeśli dobrze rozumiem, sam @Componentidzie na klasy, podczas gdy @Beanidzie na metody klasowe (które dają instancje obiektów klasy).
żartuje
182

Rozważmy, że chcę konkretnej implementacji w zależności od pewnego stanu dynamicznego. @Beanjest idealny do tego przypadku.

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

Jednak nie da się tego zrobić @Component.

przewyższyć
źródło
3
Jak nazywasz tę przykładową klasę?
PowerFlower
1
@PowerFlower Ta metoda powinna należeć do klasy konfiguracyjnej, z adnotacjami@Configuration
Juh_ 13.09.19
97

Oba podejścia mają na celu rejestrację typu docelowego w pojemniku Spring.

Różnica polega na tym, że @Beandotyczy metod , podczas gdy @Componentdotyczy typów .

Dlatego podczas korzystania z @Beanadnotacji kontrolujesz logikę tworzenia instancji w treści metody (patrz przykład powyżej ). Z @Componentadnotacją nie możesz.

Nurlan Akashayev
źródło
Jaki jest typ
Jac Frall
97
  1. @Component auto wykrywa i konfiguruje ziarna za pomocą skanowania ścieżki klas, podczas gdy @Bean wyraźnie deklaruje pojedyncze ziarno, zamiast pozwolić Springowi zrobić to automatycznie.
  2. @Component nie oddziela deklaracji fasoli od definicji klasy, podczas gdy @Bean oddziela deklarację fasoli od definicji klasy.
  3. @Component jest adnotacją na poziomie klasy, podczas gdy @Bean jest adnotacją na poziomie metody, a nazwa metody służy jako nazwa komponentu bean.
  4. @Component nie musi być używany z adnotacją @Configuration, gdy adnotacja @Bean musi być używana w klasie, która jest opatrzona adnotacją @Configuration .
  5. Nie możemy utworzyć komponentu bean klasy za pomocą @Component, jeśli klasa znajduje się poza kontenerem sprężynowym, natomiast możemy utworzyć komponent bean klasy za pomocą @Bean, nawet jeśli klasa znajduje się poza kontenerem sprężynowym .
  6. @Component ma różne specjalizacje, takie jak @Controller, @Repository i @Service, natomiast @Bean nie ma żadnych specjalizacji .
Saurabh Prakash
źródło
3
4. Właściwie @Bean może być zadeklarowany w klasie innej niż konfiguracyjna. Jest znany jako tryb lite
voipp
1
Odnośnie do punktu 5. Myślę, że włożyliśmy fasolę do wiosennego pojemnika. Tak więc każda klasa znajduje się poza pojemnikiem sprężynowym. Myślę, że punkt 5 powinien zostać nagrodzony
Eugeniusz
20

Widzę wiele odpowiedzi i prawie wszędzie wspomniany @Component służy do automatycznego okablowania, gdzie składnik jest skanowany, a @Bean dokładnie deklaruje, że fasola ma być używana w inny sposób. Pokażę, jak jest inaczej.

  • @Fasola

Najpierw jest to adnotacja na poziomie metody. Po drugie, zwykle używasz do konfigurowania komponentów bean w kodzie Java (jeśli nie używasz konfiguracji XML), a następnie wywołujesz go z klasy za pomocą metody getBean ApplicationContext. lubić

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

class User{
}



//Getting Bean 
User user = applicationContext.getBean("getUser");
  • @Składnik

Jest to ogólny sposób na adnotację fasoli, a nie fasoli specjalistycznej. Adnotacja na poziomie klasy i służy do unikania tych wszystkich czynności konfiguracyjnych za pośrednictwem konfiguracji Java lub XML.

Dostajemy coś takiego.

@Component
class User {
}

//to get Bean
@Autowired
User user;

Otóż ​​to . Został właśnie wprowadzony, aby uniknąć wszystkich kroków konfiguracji w celu utworzenia instancji i użycia tego komponentu bean.

Xpioneer
źródło
5
Myślę, że nie jest konieczne pobieranie obiektu użytkownika z ApplicationContext podczas korzystania z @Beanpodejścia. Nadal możesz użyć, @Autowireaby uzyskać fasolę, tak jak w przypadku @Component. @Beanpo prostu dodaje fasolę do kontenera wiosennego, tak jak by @Componentto zrobił . Różnica jest następująca. 1. Używając @Bean, możesz dodać Klasy Zewnętrzne do Spring Container. 2. Używając @Bean, możesz uzyskać pożądaną implementację interfejsu w czasie wykonywania (przy użyciu fabrycznego wzorca projektowego)
Andy
20

Możesz użyć, @Beanaby udostępnić istniejącą klasę innej firmy w kontekście aplikacji Spring Framework.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

Za pomocą @Beanadnotacji można owinąć klasę innej firmy (może jej nie mieć @Componenti nie używać sprężyny), jako fasolę wiosenną. A potem, gdy jest opakowany za pomocą @Bean, staje się obiektem singleton i jest dostępny w kontekście aplikacji Spring Framework. Teraz możesz łatwo udostępniać / ponownie używać tego komponentu bean w swojej aplikacji za pomocą wstrzykiwania zależności i @Autowired.

Pomyśl więc, że @Beanadnotacja jest opakowaniem / adapterem dla klas innych firm. Chcesz, aby klasy innych firm były dostępne w kontekście aplikacji Spring Framework.

Używając @Beanpowyższego kodu, jawnie deklaruję pojedynczą fasolę, ponieważ wewnątrz metody jawnie tworzę obiekt za pomocą newsłowa kluczowego. Ręcznie wywołuję również metody ustawiające danej klasy. Więc mogę zmienić wartość pola przedrostka. Tak więc ta praca ręczna jest określana jako jawne tworzenie. Jeśli użyję tego @Componentdla tej samej klasy, fasola zarejestrowana w kontenerze Spring będzie miała domyślną wartość dla pola prefiksu.

Z drugiej strony, kiedy adnotujemy klasę @Component, nie musimy ręcznie używać newsłowa kluczowego. Jest obsługiwany automatycznie przez Spring.

Elvis
źródło
1
Byłoby miło, gdyby ta odpowiedź została zaktualizowana o przykład użycia tej fasoli
softarn
Jak owinąć @Bean w klasę strony trzeciej, jeśli kod źródłowy nie pozwala na modyfikację?
veritas
16

Kiedy używasz @Componentznacznika, jest to tak samo, jak posiadanie POJO (Plain Old Java Object) z metodą deklaracji wanilii (z adnotacją @Bean). Na przykład następująca metoda 1 i 2 da ten sam wynik.

Metoda 1

@Component
public class SomeClass {

    private int number;

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

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

z fasolą dla „theNumber”:

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

Metoda 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;
    }
}

z fasolą dla obu:

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

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

Metoda 2 pozwala zachować razem deklaracje fasoli, jest nieco bardziej elastyczna itp. Możesz nawet dodać kolejną fasolę SomeClass inną niż waniliowa, jak poniżej:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}
Jakiś facet
źródło
10

Istnieją dwa sposoby generowania fasoli. Jednym z nich jest utworzenie klasy z adnotacją @Component. Drugim jest stworzenie metody i opatrzenie jej adnotacją @Bean. W przypadku klas zawierających metodę z @Beannależy dodać adnotację @Configuration Po uruchomieniu projektu wiosennego klasa z @ComponentScanadnotacją przeskanowałaby każdą klasę z @Componentnią i przywróciłaby instancję tej klasy do kontenera Ioc. Inną rzeczą, którą @ComponentScanby to zrobiło, jest uruchomienie metod . Możesz napisać logikę i zwrócić żądany obiekt. Inną rzeczą, o której warto wspomnieć, jest nazwa metody z domyślną nazwą fasoli.@Bean i przywrócenie obiektu zwracanego do kontenera Ioc jako komponentu bean. Więc kiedy musisz zdecydować, jaki rodzaj fasoli chcesz utworzyć w zależności od aktualnych stanów, musisz użyć@Bean@Bean

Dai Niu
źródło
6
  • @component i jego specjalizacje (@Controller, @service, @repository) pozwalają na automatyczne wykrywanie za pomocą skanowania ścieżki klas. Jeśli zobaczymy klasy komponentów, takie jak @Controller, @service, @repository będzie skanowane automatycznie przez strukturę Spring przy użyciu skanowania komponentów.
  • Z drugiej strony @Bean może być użyte tylko do jawnego zadeklarowania pojedynczego komponentu bean w klasie konfiguracji.
  • @Bean zwykł jawnie deklarować pojedynczą fasolę, zamiast pozwalać wiosłu automatycznie robić to. Dokonuje oddzielnej deklaracji fasoli z definicji klasy.
  • W skrócie @Controller, @service, @repository służą do automatycznego wykrywania, a @Bean do tworzenia oddzielnej fasoli z klasy
    - @Kontroler
    klasa publiczna LoginController 
    { --kod-- }

    - @Konfiguracja
    AppConfig klasy publicznej {
    @Fasola
    public SessionFactory sessionFactory () 
    {--kod-- }
alok
źródło
3

@Bean został stworzony, aby uniknąć łączenia Springa i reguł biznesowych w czasie kompilacji. Oznacza to, że możesz ponownie wykorzystywać reguły biznesowe w innych ramach, takich jak PlayFramework lub JEE.

Co więcej, masz całkowitą kontrolę nad tym, jak tworzyć fasole, gdzie nie wystarczy domyślna instancja wiosenna.

Napisałem o tym post.

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

Daniel Andres Pelaez Lopez
źródło
3

Różnica między fasolą a składnikiem:

Różnica między fasolą a komponentem

AzarEJ
źródło
1

1. Informacje o @Component @Component
działa podobnie do @Configuracja.

Oba wskazują, że klasa z adnotacjami ma co najmniej jedną fasolę, którą należy zarejestrować Spring-IOC-Container.

Klasa opatrzona adnotacją @Component, nazywamy to Component of Spring. Jest to koncepcja, która zawiera kilka ziaren.

Component classmusi zostać automatycznie przeskanowane przez Spring w celu zarejestrowania tych ziaren component class.

2. Informacje o @Bean
@Bean służy do opisywania metody component-class(jak wspomniano powyżej). Wskazuje, że wystąpienie zachowane za pomocą metody z adnotacjami wymaga rejestracji Spring-IOC-Container.

3. Wniosek
Różnica między nimi dwoma jest stosunkowo oczywista, są one używane w different circumstances. Ogólne zastosowanie to:

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

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

      @Bean
      public SecondBean SecondBeanMethod() {
        return new SecondBean();
      }
    }
Martin521Wang
źródło
0

Dodatkowe punkty z powyższych odpowiedzi

Załóżmy, że mamy moduł, który jest udostępniany w wielu aplikacjach i zawiera kilka usług. Nie wszystkie są potrzebne dla każdej aplikacji.

Jeśli używasz @Component na tych klasach usług i skanowaniu komponentów w aplikacji,

możemy w końcu wykryć więcej ziaren niż to konieczne

W takim przypadku trzeba było dostosować filtrowanie skanowania komponentu lub podać konfigurację, która może działać nawet nieużywane komponenty bean. W przeciwnym razie kontekst aplikacji nie uruchomi się.

W takim przypadku lepiej jest pracować z adnotacją @Bean i tworzyć tylko te fasole,

które są wymagane osobno w każdej aplikacji

Zasadniczo użyj @Bean do dodania klas stron trzecich do kontekstu. I @Component, jeśli jest tylko w jednej aplikacji.

AzarEJ
źródło