Frühling: @Component versus @Bean

459

Ich verstehe, dass die @ComponentAnnotation im Frühjahr 2.5 eingeführt wurde, um die XML-Bean-Definition mithilfe des Klassenpfad-Scannens zu entfernen.

@Beanwurde im Frühjahr 3.0 eingeführt und kann verwendet @Configurationwerden, um die XML-Datei vollständig zu entfernen und stattdessen die Java-Konfiguration zu verwenden.

Wäre es möglich gewesen, die @ComponentAnmerkung wiederzuverwenden, anstatt eine @BeanAnmerkung einzuführen ? Mein Verständnis ist, dass das Endziel in beiden Fällen darin besteht, Bohnen zu erzeugen.

user1396576
quelle
4
Gibt es irgendwo, wo @Bean außer der Konfigurationsklasse verwendet werden kann?
Willa
@Willa Ja, das gibt es. Das heißt Lite mode. Und es wird nicht empfohlen. Siehe hier: docs.spring.io/spring/docs/current/spring-framework-reference/…
smwikipedia
9
Ich würde es zusammenfassen und sagen, dass eine Methode mit @beaneiner anpassbaren Instanz von Spring Bean zurückgibt, während @componenteine Klasse definiert wird, die später bei Bedarf von der Spring IoC-Engine instanziiert werden kann.
Sebas

Antworten:

433

@Componentund @Beanmache zwei ganz verschiedene Dinge und sollte nicht verwechselt werden.

@Component(und @Serviceund @Repository) werden verwendet, um Beans mithilfe des Klassenpfad-Scans automatisch zu erkennen und zu konfigurieren. Es gibt eine implizite Eins-zu-Eins-Zuordnung zwischen der mit Anmerkungen versehenen Klasse und der Bean (dh einer Bean pro Klasse). Die Steuerung der Verkabelung ist bei diesem Ansatz sehr begrenzt, da er rein deklarativ ist.

@Beanwird verwendet , um eine einzelne Bean explizit zu deklarieren, anstatt Spring dies wie oben automatisch tun zu lassen. Es entkoppelt die Deklaration der Bean von der Klassendefinition und ermöglicht es Ihnen, Beans genau nach Ihren Wünschen zu erstellen und zu konfigurieren.

Zur Beantwortung Ihrer Frage...

Wäre es möglich gewesen, die @ComponentAnmerkung wiederzuverwenden, anstatt eine @BeanAnmerkung einzuführen ?

Sicher wahrscheinlich; aber sie entschieden sich dagegen, da die beiden sehr unterschiedlich sind. Der Frühling ist schon verwirrend genug, ohne das Wasser weiter zu trüben.

Skaffman
quelle
3
Also kann ich nur verwenden, @Componentwenn Autowired benötigt wird? Es scheint @Beannicht zu beeinflussen@Autowired
Jaskey
3
Verwenden Sie '@component' für service-basierte Klassen, '@Bean' als fabrikspezifischere Objekte, z. B. jdbc-Datenquelle
Junchen Liu
2
@ Jaskey, den Sie verwenden können, wenn Sie Ihre Bohnenklasse @Autowiredmit @Beankommentiert haben@Configuration
starcorn
6
Entschuldigung, aber ich kann kein Wort Ihrer Erklärung verstehen. Sie verstehen das klar und deutlich. Würden Sie bitte eine klare Erklärung schreiben oder auf die entsprechende Dokumentation verweisen?
Alex Worden
13
Nachdem ich das Konzept verstanden habe (indem ich die Antworten anderer gelesen habe), ist Ihre Erklärung sinnvoll. Umso mehr sagt mir das, dass Ihre Erklärung für niemanden gut ist, der die Konzepte noch nicht versteht.
Alex Worden
397

@Komponente Bevorzugt für das Scannen von Komponenten und die automatische Verkabelung.

Wann sollten Sie @Bean verwenden ?

Manchmal ist eine automatische Konfiguration keine Option. Wann?Stellen Sie sich vor, Sie möchten Komponenten aus Bibliotheken von Drittanbietern verkabeln (Sie haben keinen Quellcode, sodass Sie die Klassen nicht mit @Component kommentieren können), sodass eine automatische Konfiguration nicht möglich ist.

Die Annotation @Bean gibt ein Objekt zurück , das spring im Anwendungskontext als Bean registrieren soll. Der Hauptteil der Methode trägt die Logik, die für die Erstellung der Instanz verantwortlich ist.

MagGGG
quelle
5
Ich denke, das macht am meisten Sinn. Wenn ich das richtig verstehe, @Componentgeht es um Klassen selbst, während es @Beanum Klassenmethoden geht (die Instanzen von Klassenobjekten ergeben).
Jocull
182

Nehmen wir an, ich möchte eine spezifische Implementierung in Abhängigkeit von einem dynamischen Zustand. @Beanist perfekt für diesen Fall.

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

Es gibt jedoch keine Möglichkeit, dies zu tun @Component.

outdev
quelle
3
Wie nennt man diese Beispielklasse?
PowerFlower
1
@ PowerFlower Diese Methode sollte in einer Konfigurationsklasse sein, kommentiert mit@Configuration
Juh_
98
  1. @Component erkennt und konfiguriert die Beans automatisch mithilfe des Klassenpfad-Scans, während @Bean explizit eine einzelne Bean deklariert , anstatt Spring dies automatisch tun zu lassen.
  2. @Component entkoppelt die Deklaration der Bean nicht von der Klassendefinition, während @Bean die Deklaration der Bean von der Klassendefinition entkoppelt .
  3. @Component ist eine Klassenstufe Anmerkung während @Bean ist ein Verfahren Ebene Annotation und den Name des Verfahrens dient , wie der Name Bohne.
  4. @Component muss nicht mit der Annotation @Configuration verwendet werden, wobei die Annotation @Bean innerhalb der mit @Configuration annotierten Klasse verwendet werden muss .
  5. Wir können keine Bean einer Klasse mit @Component erstellen, wenn sich die Klasse außerhalb des Spring-Containers befindet, während wir mit @Bean eine Bean einer Klasse erstellen können, selbst wenn die Klasse außerhalb des Spring-Containers vorhanden ist .
  6. @Component hat verschiedene Spezialisierungen wie @Controller, @Repository und @Service, während @Bean keine Spezialisierungen hat .
Saurabh Prakash
quelle
3
4. Tatsächlich könnte @Bean in einer Nicht-Konfigurationsklasse deklariert werden. Es ist als Lite-Modus bekannt
Voipp
1
Zu Punkt 5. Ich denke, wir haben eine Bohne in den Federbehälter gelegt. Jede Klasse befindet sich also außerhalb des Federbehälters. Ich denke, Punkt 5 sollte belohnt werden
Eugen
97

Beide Ansätze zielen darauf ab, den Zieltyp im Spring-Container zu registrieren.

Der Unterschied besteht darin, dass dies @Beanfür Methoden gilt , während dies @Componentfür Typen gilt .

Wenn Sie also @BeanAnmerkungen verwenden, steuern Sie die Instanzerstellungslogik im Hauptteil der Methode (siehe Beispiel oben ). Mit @ComponentAnnotation können Sie nicht.

Nurlan Akashayev
quelle
Was ist ein Typ?
Jac Frall
20

Ich sehe viele Antworten und fast überall ist die erwähnte @Component für das automatische Verdrahten gedacht, wo die Komponente gescannt wird und @Bean genau erklärt, dass die Bean anders verwendet werden soll. Lassen Sie mich zeigen, wie es anders ist.

  • @Bohne

Zuerst ist es eine Annotation auf Methodenebene. Zweitens verwenden Sie im Allgemeinen die Konfiguration von Beans in einem Java-Code (wenn Sie keine XML-Konfiguration verwenden) und rufen sie dann mit der getBean-Methode von ApplicationContext aus einer Klasse auf. mögen

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

class User{
}



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

Es ist eine allgemeine Methode, eine Bohne und keine spezialisierte Bohne mit Anmerkungen zu versehen. Eine Annotation auf Klassenebene, die verwendet wird, um all das Konfigurationsmaterial durch Java- oder XML-Konfiguration zu vermeiden.

Wir bekommen so etwas.

@Component
class User {
}

//to get Bean
@Autowired
User user;

Das ist es . Es wurde nur eingeführt, um alle Konfigurationsschritte zum Instanziieren und Verwenden dieser Bean zu vermeiden.

xpioneer
quelle
5
Ich denke, es ist nicht notwendig, das Benutzerobjekt von ApplicationContext abzurufen, wenn Sie den @BeanAnsatz verwenden. Sie können @Autowiredie Bohne weiterhin verwenden , wie Sie es im Fall von tun würden @Component. @BeanFügt die Bohne einfach wie gewohnt zum Frühlingsbehälter hinzu @Component. Der Unterschied ist wie folgt. 1. Mit @Beankönnen Sie Spring Container Klassen von Drittanbietern hinzufügen. 2. Mit @Beankönnen Sie die gewünschte Implementierung einer Schnittstelle zur Laufzeit erhalten (unter Verwendung des Factory-Design-Musters)
Andy
20

Sie können verwenden @Bean, um eine vorhandene Klasse eines Drittanbieters für Ihren Spring Framework-Anwendungskontext verfügbar zu machen.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

Mithilfe der @BeanAnmerkung können Sie eine Klasse eines Drittanbieters (die möglicherweise nicht über @ComponentSpring verfügt und Spring nicht verwendet) als Spring Bean einbinden. Sobald es mit verpackt ist, @Beanist es ein Singleton-Objekt und in Ihrem Spring Framework-Anwendungskontext verfügbar. Sie können diese Bean jetzt mithilfe der Abhängigkeitsinjektion und einfach in Ihrer App freigeben / wiederverwenden@Autowired .

Denken Sie also an die @Bean Annotation ist ein Wrapper / Adapter für Klassen von Drittanbietern. Sie möchten die Klassen von Drittanbietern für Ihren Spring Framework-Anwendungskontext verfügbar machen.

Mit @Beandem obigen Code deklariere ich explizit eine einzelne Bean, da ich innerhalb der Methode das Objekt explizit mit dem newSchlüsselwort erstelle . Ich rufe auch manuell Setter-Methoden der angegebenen Klasse auf. So kann ich den Wert des Präfixfeldes ändern. Daher wird diese manuelle Arbeit als explizite Erstellung bezeichnet. Wenn ich das benutze@Component für dieselbe Klasse verwende, hat die im Spring-Container registrierte Bean den Standardwert für das Präfixfeld.

Wenn wir dagegen eine Klasse mit Anmerkungen versehen @Component, müssen wir das newSchlüsselwort nicht manuell verwenden . Es wird automatisch von Spring behandelt.

Elvis
quelle
1
Wäre schön, wenn diese Antwort mit einem Beispiel für die Verwendung dieser Bohne aktualisiert würde
Softarn
Wie würden Sie eine @ Bean über eine Klasse eines Drittanbieters wickeln, wenn der Quellcode keine Änderung zulässt?
Veritas
16

Wenn Sie das @ComponentTag verwenden, entspricht dies einem POJO (Plain Old Java Object) mit einer Vanillebohnen-Deklarationsmethode (mit Anmerkungen versehen @Bean). Beispielsweise ergeben die folgenden Methoden 1 und 2 das gleiche Ergebnis.

Methode 1

@Component
public class SomeClass {

    private int number;

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

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

mit einer Bohne für 'theNumber':

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

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

mit den Bohnen für beide:

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

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

Mit Methode 2 können Sie Bean-Deklarationen zusammenhalten, sie sind etwas flexibler usw. Möglicherweise möchten Sie sogar eine andere SomeClass-Bean ohne Vanille wie die folgende hinzufügen:

@Bean
SomeClass strawberryClass(){
    return new SomeClass(new Integer(1));
}
Irgendein Typ
quelle
10

Sie haben zwei Möglichkeiten, Bohnen zu generieren. Eine besteht darin, eine Klasse mit einer Anmerkung zu erstellen @Component. Die andere besteht darin, eine Methode zu erstellen und mit Anmerkungen zu versehen @Bean. Für Klassen, die Methoden mit enthalten, @Beansollte eine Annotation mit vorhanden sein. @Configuration Sobald Sie Ihr Spring-Projekt ausgeführt haben, @ComponentScanscannt die Klasse mit einer Annotation jede Klasse mit @Componentdieser Annotation und stellt die Instanz dieser Klasse im Ioc-Container wieder her. Eine andere Sache, die Sie @ComponentScantun würden, ist, die Methoden mit @Beandarauf auszuführen und das Rückgabeobjekt als Bean im Ioc-Container wiederherzustellen. Wenn Sie also entscheiden müssen, welche Art von Bohnen Sie abhängig vom aktuellen Status erstellen möchten, müssen Sie diese verwenden@Bean . Sie können die Logik schreiben und das gewünschte Objekt zurückgeben. Eine andere erwähnenswerte Sache ist der Name der Methode, wobei @Beander Standardname der Bean ist.

Dai Niu
quelle
6
  • @component und seine Spezialisierungen (@Controller, @service, @repository) ermöglichen die automatische Erkennung mithilfe des Scannens von Klassenpfaden. Wenn Komponentenklassen wie @Controller, @service, @repository angezeigt werden, wird @repository mithilfe des Komponentenscans automatisch vom Spring Framework gescannt.
  • @Bean hingegen kann nur verwendet werden, um eine einzelne Bean in einer Konfigurationsklasse explizit zu deklarieren.
  • @Bean deklarierte eine einzelne Bean explizit, anstatt Spring dies automatisch tun zu lassen. Es macht septate Deklaration von Bean aus der Klassendefinition.
  • Kurz gesagt, @Controller, @service, @repository dienen zur automatischen Erkennung und @Bean zum Erstellen einer separaten Bean aus der Klasse
    - @ Controller
    öffentliche Klasse LoginController 
    {--code--}

    - @Aufbau
    öffentliche Klasse AppConfig {
    @Bohne
    public SessionFactory sessionFactory () 
    {--code--}
alok
quelle
3

@Bean wurde erstellt, um zu vermeiden, dass Spring und Ihre Geschäftsregeln in der Kompilierungszeit gekoppelt werden. Dies bedeutet, dass Sie Ihre Geschäftsregeln in anderen Frameworks wie PlayFramework oder JEE wiederverwenden können.

Darüber hinaus haben Sie die vollständige Kontrolle darüber, wie Beans erstellt werden, wobei die Standard-Spring-Instanzation nicht ausreicht.

Ich habe einen Beitrag darüber geschrieben.

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

Daniel Andres Pelaez Lopez
quelle
3

Unterschied zwischen Bean und Komponente:

Unterschied zwischen Bean und Component

AzarEJ
quelle
1

1. Über @Component
@Component funktioniert ähnlich wie @Configuration.

Beide geben an, dass für die mit Anmerkungen versehene Klasse eine oder mehrere Beans registriert werden müssen Spring-IOC-Container.

Die von @Component annotierte Klasse nennen wir sie Component of Spring. Es ist ein Konzept, das mehrere Bohnen enthält.

Component classmuss von Spring automatisch gescannt werden, um die Bohnen der zu registrieren component class.

2. Über @Bean
@Bean wird verwendet, um die Methode von component-class(wie oben erwähnt) zu kommentieren . Es zeigt an, dass die Instanz, die durch die mit Anmerkungen versehene Methode wiederhergestellt wurde, registriert werden muss Spring-IOC-Container.

3. Fazit
Der Unterschied zwischen den beiden ist relativ offensichtlich, sie werden in verwendet different circumstances. Die allgemeine Verwendung ist:

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

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

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

Zusätzliche Punkte aus den obigen Antworten

Angenommen, wir haben ein Modul, das in mehreren Apps gemeinsam genutzt wird und einige Dienste enthält. Nicht alle werden für jede App benötigt.

Wenn Sie @Component für diese Serviceklassen und den Komponentenscan in der Anwendung verwenden,

Möglicherweise entdecken wir mehr Bohnen als nötig

In diesem Fall mussten Sie entweder die Filterung des Komponentenscans anpassen oder die Konfiguration bereitstellen, die auch die nicht verwendeten Beans ausführen können. Andernfalls wird der Anwendungskontext nicht gestartet.

In diesem Fall ist es besser, mit der @ Bean-Annotation zu arbeiten und nur diese Beans zu instanziieren.

die in jeder App einzeln benötigt werden

Verwenden Sie also im Wesentlichen @Bean, um dem Kontext Klassen von Drittanbietern hinzuzufügen. Und @Component, wenn es sich nur in Ihrer einzelnen Anwendung befindet.

AzarEJ
quelle