Primavera: @Component contro @Bean


459

Comprendo che l' @Componentannotazione è stata introdotta nella primavera 2.5 per eliminare la definizione del bean XML utilizzando la scansione del percorso di classe.

@Beanè stato introdotto nella primavera 3.0 e può essere utilizzato con @Configurationper eliminare completamente il file XML e utilizzare invece java config.

Sarebbe stato possibile riutilizzare l' @Componentannotazione invece di introdurla @Bean? La mia comprensione è che l'obiettivo finale è quello di creare fagioli in entrambi i casi.


4
Esiste un punto in cui @Bean può essere utilizzato oltre alla classe di configurazione?
Willa,


@Willa Sì, c'è. Questo si chiama Lite mode. E non è raccomandato Vedi qui: docs.spring.io/spring/docs/current/spring-framework-reference/…
smwikipedia

9
Lo riassumo dicendo che un metodo con @beanrestituisce un'istanza personalizzabile di bean di primavera, mentre @componentdefinisce una classe che può essere successivamente istanziata dal motore IoC di primavera quando necessario.
Sebas

Risposte:


433

@Componente @Beanfai due cose abbastanza diverse, e non dovresti essere confuso.

@Component(e @Servicee @Repository) vengono utilizzati per rilevare e configurare automaticamente i bean mediante la scansione del percorso di classe. Esiste un mapping uno a uno implicito tra la classe annotata e il bean (ovvero un bean per classe). Il controllo del cablaggio è piuttosto limitato con questo approccio, poiché è puramente dichiarativo.

@Beanè usato per dichiarare esplicitamente un singolo bean, piuttosto che lasciare che Spring lo faccia automaticamente come sopra. Disaccoppia la dichiarazione del bean dalla definizione della classe e consente di creare e configurare i bean esattamente come si sceglie.

Per rispondere alla tua domanda ...

sarebbe stato possibile riutilizzare l' @Componentannotazione anziché introdurla @Bean?

Certo, probabilmente; ma hanno scelto di non farlo, poiché i due sono abbastanza diversi. La primavera è già abbastanza confusa senza confondere ulteriormente le acque.


3
Quindi posso usare solo @Componentquando è necessario autowired? Sembra che @Beannon possa influenzare@Autowired
Jaskey il

3
usa '@component' per le classi basate sul servizio, '@Bean' come fabbrica più oggetti su misura, ad esempio origine dati jdbc
Junchen Liu

2
@Jaskey si può usare @Autowiredcon @Beanse si è annotata la classe di fagioli con@Configuration
starcorn

6
Scusa ma non riesco a capire una parola della tua spiegazione. Lo capisci chiaramente, quindi ti preghiamo di scrivere una spiegazione chiara o di indicare la documentazione appropriata?
Alex Worden,

13
Ora che capisco il concetto (dalla lettura delle risposte degli altri), la tua spiegazione ha un senso. Il che mi dice ancora di più che la tua spiegazione non è buona per nessuno che non capisce già i concetti.
Alex Worden,

397

@Component Preferibile per la scansione dei componenti e il cablaggio automatico.

Quando dovresti usare @Bean ?

A volte la configurazione automatica non è un'opzione. Quando? Immaginiamo di voler collegare componenti da librerie di terze parti (non hai il codice sorgente, quindi non puoi annotare le sue classi con @Component), quindi la configurazione automatica non è possibile.

L' annotazione @Bean restituisce un oggetto che spring dovrebbe registrare come bean nel contesto dell'applicazione. Il corpo del metodo porta la logica responsabile della creazione dell'istanza.


5
Penso che questo abbia più senso. Se ho capito bene @Componentva sulle classi stesse mentre @Beanva sui metodi di classe (che producono istanze di oggetti di classe).
Giocate il

182

Consideriamo che voglio un'implementazione specifica a seconda di uno stato dinamico. @Beanè perfetto per quel caso.

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

Tuttavia non c'è modo di farlo con @Component.


3
Come si chiama quella classe di esempio?
PowerFlower

1
@PowerFlower Questo metodo dovrebbe essere in una classe di configurazione, annotato con@Configuration
Juh_

98
  1. @Component rileva e configura automaticamente i bean usando la scansione del classpath mentre @Bean dichiara esplicitamente un singolo bean, invece di lasciare che Spring lo faccia automaticamente.
  2. @Component non disaccoppia la dichiarazione del bean dalla definizione della classe dove @Bean disaccoppia la dichiarazione del bean dalla definizione della classe.
  3. @Component è un'annotazione a livello di classe mentre @Bean è un'annotazione a livello di metodo e il nome del metodo funge da nome del bean.
  4. Non è necessario utilizzare @Component con l' annotazione @Configuration, mentre l' annotazione @Bean deve essere utilizzata all'interno della classe annotata con @Configuration .
  5. Non è possibile creare un bean di una classe utilizzando @Component, se la classe è al di fuori del contenitore spring mentre possiamo creare un bean di una classe utilizzando @Bean anche se la classe è presente al di fuori del contenitore spring .
  6. @Component ha diverse specializzazioni come @Controller, @Repository e @Service mentre @Bean non ha specializzazioni .

3
4. In realtà @Bean potrebbe essere dichiarato in una classe non di configurazione. È noto come modalità lite
voipp

1
Per quanto riguarda il punto 5. Penso che abbiamo messo un fagiolo nel contenitore a molla. Quindi, ogni classe è fuori dal contenitore di primavera. Immagino che il punto 5 dovrebbe essere premiato
eugen il

97

Entrambi gli approcci mirano a registrare il tipo di target nel contenitore Spring.

La differenza è @Beanapplicabile ai metodi , mentre @Componentai tipi .

Pertanto, quando si utilizza l' @Beanannotazione, si controlla la logica di creazione dell'istanza nel corpo del metodo (vedere l' esempio sopra ). Con l' @Componentannotazione non puoi.


Che cos'è un tipo?
Jac Frall,

20

Vedo molte risposte e quasi ovunque la sua menzionata @Component è per il collegamento automatico in cui il componente viene scansionato e @Bean dichiara esattamente che il bean deve essere utilizzato in modo diverso. Lasciami mostrare come è diverso.

  • @Fagiolo

Innanzitutto è un'annotazione a livello di metodo. Secondo, generalmente si usano per configurare i bean in un codice Java (se non si utilizza la configurazione XML) e quindi lo si chiama da una classe usando il metodo getBean di ApplicationContext. piace

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

class User{
}



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

È un modo generale per annotare un bean e non un bean specializzato. Un'annotazione a livello di classe e viene utilizzata per evitare tutte quelle cose di configurazione attraverso la configurazione Java o XML.

Abbiamo qualcosa del genere.

@Component
class User {
}

//to get Bean
@Autowired
User user;

Questo è tutto . È stato appena introdotto per evitare tutte le fasi di configurazione per istanziare e utilizzare quel bean.


5
Penso che non sia necessario ottenere l'oggetto Utente da ApplicationContext quando si utilizza l' @Beanapproccio. Puoi ancora usare @Autowireper ottenere il bean come faresti in caso di @Component. @Beanaggiunge semplicemente il fagiolo al contenitore di primavera proprio come farebbe @Component. La differenza è la seguente. 1. Utilizzando @Bean, è possibile aggiungere classi di terze parti a Spring Container. 2. Utilizzando @Bean, è possibile ottenere l'implementazione desiderata di un'interfaccia in fase di esecuzione (utilizzando il modello di progettazione di fabbrica)
Andy,

20

È possibile utilizzare @Beanper rendere disponibile una classe di terze parti esistente nel contesto dell'applicazione Spring Framework.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

Utilizzando l' @Beanannotazione, è possibile racchiudere una classe di terze parti (potrebbe non essere disponibile @Componente non utilizzare Spring), come bean Spring. E poi, una volta avvolto usando @Bean, è come un oggetto singleton e disponibile nel contesto dell'applicazione Spring Framework. Ora puoi facilmente condividere / riutilizzare questo bean nella tua app usando l'iniezione delle dipendenze e @Autowired.

Quindi pensare @Beanall'annotazione è un wrapper / adattatore per classi di terze parti. Si desidera rendere le classi di terze parti disponibili per il contesto dell'applicazione Spring Framework.

Usando @Beanil codice sopra, dichiaro esplicitamente un singolo bean perché all'interno del metodo, sto creando esplicitamente l'oggetto usando la newparola chiave. Sto anche chiamando manualmente i metodi setter di una determinata classe. Quindi posso cambiare il valore del campo prefisso. Quindi questo lavoro manuale viene definito creazione esplicita. Se uso la @Componentstessa classe, il bean registrato nel contenitore Spring avrà un valore predefinito per il campo prefisso.

D'altra parte, quando annotiamo una classe con @Component, non è necessario che usiamo manualmente la newparola chiave. Viene gestito automaticamente da Spring.


1
Sarebbe bello se questa risposta fosse aggiornata con un esempio di come viene utilizzato anche quel bean
softarn

Come avvolgeresti un @Bean su una classe di terze parti se il codice sorgente non consente la modifica?
veritas

16

Quando si utilizza il @Componenttag, è lo stesso che avere un POJO (Plain Old Java Object) con un metodo di dichiarazione del bean vanilla (annotato con @Bean). Ad esempio, i seguenti metodi 1 e 2 daranno lo stesso risultato.

Metodo 1

@Component
public class SomeClass {

    private int number;

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

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

con un bean per "theNumber":

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

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

con i fagioli per entrambi:

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

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

Il metodo 2 ti consente di tenere insieme le dichiarazioni dei bean, è un po 'più flessibile, ecc. Potresti anche voler aggiungere un altro bean SomeClass non vanilla come il seguente:

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

10

Hai due modi per generare fagioli. Uno è quello di creare una classe con un'annotazione @Component. L'altro è creare un metodo e annotarlo con @Bean. Per quelle classi che contengono il metodo con @Beandevono essere annotate con @Configuration Una volta eseguito il progetto di primavera, la classe con @ComponentScanun'annotazione eseguirà la scansione di ogni classe con @Componentsu di essa e ripristinerà l'istanza di questa classe nel contenitore Ioc. Un'altra cosa @ComponentScanda fare è eseguire i metodi con @Beansu di esso e ripristinare l'oggetto di ritorno in Ioc Container come un bean. Pertanto, quando è necessario decidere quale tipo di bean si desidera creare in base agli stati correnti, è necessario utilizzare@Bean. È possibile scrivere la logica e restituire l'oggetto desiderato. Un'altra cosa degna di nota è il nome del metodo con @Beanè il nome predefinito del bean.


6
  • @component e le sue specializzazioni (@Controller, @service, @repository) consentono il rilevamento automatico tramite la scansione del percorso di classe. Se vediamo una classe di componenti come @Controller, @service, @repository verrà scansionata automaticamente dal framework di primavera usando la scansione dei componenti.
  • D'altra parte, @Bean può essere utilizzato solo per dichiarare esplicitamente un singolo bean in una classe di configurazione.
  • @Bean era solito dichiarare esplicitamente un singolo bean, piuttosto che lasciare che Spring lo facesse automaticamente. Fa una dichiarazione separata del bean dalla definizione della classe.
  • In breve @Controller, @service, @repository sono per il rilevamento automatico e @Bean per creare bean separati dalla classe
    - @Controller
    LoginController di classe pubblica 
    { --codice-- }

    - @Configuration
    AppConfig di classe pubblica {
    @Fagiolo
    public SessionFactory sessionFactory () 
    {--codice-- }



1

1. Informazioni su @Component
@Component funziona in modo simile a @Configuration.

Entrambi indicano che la classe annotata ha uno o più bean in cui è necessario essere registrati Spring-IOC-Container.

La classe annotata da @Component, la chiamiamo Component of Spring. È un concetto che contiene diversi fagioli.

Component classdeve essere scansionato automaticamente da Spring per la registrazione di quei bean di component class.

2. Informazioni su @Bean
@Bean viene utilizzato per annotare il metodo di component-class(come menzionato sopra). Indica che l'istanza trattenuta dal metodo annotato deve essere registrata Spring-IOC-Container.

3. Conclusione
La differenza tra loro due è relativamente ovvia, in cui vengono utilizzati different circumstances. L'uso generale è:

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

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

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

0

Punti aggiuntivi dalle risposte sopra

Diciamo che abbiamo un modulo che è condiviso in più app e contiene alcuni servizi. Non tutte sono necessarie per ogni app.

Se usi @Component su tali classi di servizio e la scansione dei componenti nell'applicazione,

potremmo finire per rilevare più fagioli del necessario

In questo caso, è stato necessario regolare il filtro della scansione dei componenti o fornire la configurazione che può essere eseguita anche dai bean inutilizzati. In caso contrario, il contesto dell'applicazione non verrà avviato.

In questo caso, è meglio lavorare con l'annotazione @Bean e istanziare solo quei bean,

che sono richiesti individualmente in ogni app

Quindi, in sostanza, utilizzare @Bean per aggiungere classi di terze parti al contesto. E @Component se si trova all'interno della tua singola applicazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.