web-dev-qa-db-fra.com

Spring: @Component versus @Bean

Je comprends que l’annotation @Component a été introduite au printemps 2.5 afin de supprimer la définition du bean xml à l’aide du balayage classpath.

@Bean a été introduit au printemps 3.0 et peut être utilisé avec @Configuration afin de supprimer complètement le fichier xml et d'utiliser la configuration Java à la place.

Aurait-il été possible de réutiliser l'annotation @Component au lieu d'introduire une annotation @Bean? Je crois comprendre que l'objectif final est de créer des haricots dans les deux cas.

284
user1396576

@Component et @Bean font deux choses bien différentes et ne doivent pas être confondus.

@Component (et @Service et @Repository) sont utilisés pour détecter et configurer automatiquement les beans à l'aide de l'analyse de chemin d'accès aux classes. Il existe un mappage un à un implicite entre la classe annotée et le bean (c'est-à-dire un bean par classe). Le contrôle du câblage est assez limité avec cette approche, car elle est purement déclarative.

@Bean est utilisé pour explicitement déclarer un seul haricot, plutôt que de laisser Spring le faire automatiquement comme ci-dessus. Il sépare la déclaration du bean de la définition de classe et vous permet de créer et de configurer des beans exactement comme vous le souhaitez.

Pour répondre à ta question...

aurait-il été possible de réutiliser l'annotation @Component au lieu d'introduire une annotation @Bean

Bien sûr, probablement; mais ils ont choisi de ne pas le faire, car les deux sont très différents. Le printemps est déjà assez déroutant sans pour autant brouiller les eaux.

313
skaffman

@Component Préférable pour la numérisation de composants et le câblage automatique. 

Quand devriez-vous utiliser @Bean ? 

Parfois, la configuration automatique n'est pas une option. Quand? Imaginons que vous souhaitiez câbler des composants à partir de bibliothèques tierces (vous ne disposez pas du code source et vous ne pouvez donc pas annoter ses classes avec @Component), de sorte qu'une configuration automatique n'est pas possible. 

Le @Bean annotation renvoie un objet ce ressort devrait être enregistré comme bean dans le contexte de l'application. Le corps de la méthode porte la logique responsable de la création de l'instance.

214
MagGGG

Considérons que je veux une implémentation spécifique en fonction d'un état dynamique .@Bean est parfait pour ce cas.

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

Cependant, il n'y a aucun moyen de faire cela avec @Component.

137
outdev

Les deux approches visent à enregistrer le type de cible dans le conteneur Spring.

La différence est que @Bean est applicable à methods, alors que @Component est applicable à types.

Par conséquent, lorsque vous utilisez l'annotation @Bean, vous contrôlez la logique de création d'instance dans le corps de la méthode (voir exemple ci-dessus ). Avec l'annotation @Component, vous ne pouvez pas.

62
Nurlan
  1. @Component auto détecte et configure les beans à l'aide du balayage de chemin de classe, tandis que @Bean déclare explicitement un seul bean, plutôt que de laisser Spring le faire automatiquement.
  2. @Component ne découple pas la déclaration du bean de la définition de classe alors que, comme @Bean decouples, la déclaration du bean de la définition de la classe.
  3. @Component est une annotation de niveau classe, où @Bean est une annotation de niveau méthode, et le nom de la méthode sert de nom de bean.
  4. @Component n'a pas besoin d'être utilisé avec l'annotation @Configuration où l'annotation @Bean doit être utilisée dans la classe annotée avec @Configuration
  5. Nous ne pouvons pas créer un bean d'une classe à l'aide de @Component, si la classe est en dehors du conteneur spring alors que nous pouvons créer un bean d'une classe en utilisant @Bean même si la classe est présente en dehors du printemps récipient.
  6. @Component a différentes spécialisations comme @Controller, @Repository et @Service alors que @Bean a pas de spécialisations.
36
saurabh prakash

@Component .__ Ceci est une annotation générique et peut être appliqué à n'importe quelle classe de l'application pour en faire un composant géré par le ressort (simplement, le stéréotype générique de tout composant géré par le ressort). lorsque le chemin de classe est analysé par composant-scan (@ComponentScan) feature, il identifiera les classes annotées avec @Component annotation (dans le package donné) et créera les beans de ces classes et sera enregistré les dans ApplicationContext. @Component est une annotation au niveau de la classe. Son objectif est de faire de la classe un composant géré par un ressort et un bean détectable automatiquement pour la fonction d'analyse de chemin d'accès aux classes.

si vous souhaitez en savoir plus sur @Component et d'autres annotations stéréotypées, il est recommandé de consulter cet article.

@Bean est utilisé pour déclarer et enregistrer explicitement un bean (en tant que bean de configuration) dans le conteneur Spring IOC renvoyé par une méthode. @Bean est une annotation au niveau de la méthode utilisée dans une classe annotée avec @Configuration . Simplement, l'annotation @Bean est utilisée pour enregistrer le bean renvoyé par une méthode en tant que bean de configuration de ressort dans IOC Container. @Bean n'est qu'une annotation au niveau de la méthode et ne peut pas être utilisé avec les classes et la déclaration d'objet.

@Bean annotation indique qu'une méthode produit un bean qui devrait être géré par le conteneur Spring.

Pour déclarer un bean, annotez simplement une méthode avec l'annotation @Bean . Lorsque JavaConfig rencontre une telle méthode, il l'exécute et enregistre la valeur de retour sous forme de bean dans un ApplicationContext. Par défaut, le nom du bean sera le même que le nom de la méthode. Voici un exemple simple d'une déclaration de méthode @Bean.

@Configuration
public class ApplicationConfig {

    @Bean
    public User adminUserProfile() {
        return new User("Rami","Nassar");
    }
}

Dans la classe ApplicationConfig, vous pouvez voir que nous utilisons d'abord l'annotation @Configuration pour informer Spring qu'il s'agit d'un fichier de configuration basé sur Java. Ensuite, l'annotation @Bean est utilisée pour déclarer un bean Spring et les exigences DI .. .. .L'annotation @Bean est équivalente à la balise, le nom de la méthode est équivalent à la Attribut id dans la balise... J'espère qu'après avoir lu cet article, vous aurez une idée précise du but réel et de l'utilisation de @Bean et @Component annotations.

17
Rami Nassar

Lorsque vous utilisez la balise @Component, cela revient à avoir un POJO (Plain Old Java Object) avec une méthode de déclaration de bean Vanilla (annoté avec @Bean). Par exemple, les méthodes suivantes 1 et 2 donneront le même résultat.

Méthode 1

@Component
public class SomeClass {

    private int number;

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

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

avec un haricot pour 'theNumber':

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

Méthode 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;
    }
}

avec les haricots pour les deux:

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

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

La méthode 2 vous permet de regrouper les déclarations de beans, c'est un peu plus flexible, etc. Vous pouvez même vouloir ajouter un autre bean non Vanilla SomeClass, comme suit:

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

Vous pouvez utiliser @Bean pour mettre à disposition une classe tierce existante dans le contexte de votre application-cadre Spring.

@Bean
public ViewResolver viewResolver() {

    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

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

    return viewResolver;
}

En utilisant l'annotation @Bean, vous pouvez envelopper une classe tierce (elle peut ne pas avoir @Component et ne pas utiliser Spring), en tant que bean Spring. Et ensuite, une fois encapsulé avec @Bean, il se présente sous la forme d'un objet singleton et disponible dans votre contexte d'application du framework Spring. Vous pouvez maintenant facilement partager/réutiliser ce bean dans votre application à l'aide de l'injection de dépendance et de @Autowired.

Alors, pensez à l'annotation @Bean qui est un wrapper/adaptateur pour les classes tierces. Vous souhaitez rendre les classes tierces disponibles pour votre contexte d'application du framework Spring.

En utilisant @Bean dans le code ci-dessus, je déclare explicitement un seul bean car, à l'intérieur de la méthode, je crée explicitement l'objet à l'aide du mot clé new. J'appelle aussi manuellement les méthodes de définition de la classe donnée. Je peux donc changer la valeur du champ de préfixe. Donc, ce travail manuel est appelé création explicite. Si j'utilise le @Component pour la même classe, le bean enregistré dans le conteneur Spring aura la valeur par défaut pour le champ de préfixe.

Par contre, lorsque nous annotons une classe avec @Component, il n'est pas nécessaire que nous utilisions manuellement le mot clé new. Il est géré automatiquement par Spring.

3
elvis
  • @component et ses spécialisations (@Controller, @service, @repository) permettent la détection automatique à l'aide du balayage de chemin de classes. Si nous voyons une classe de composants comme @Controller, @service, @repository sera analysée automatiquement par le framework Spring, à l'aide de l'analyse de composant.
  • @Bean, d'autre part, ne peut être utilisé que pour déclarer explicitement un seul bean dans une classe de configuration. 
  • @Bean déclarait explicitement un seul haricot, plutôt que de laisser Spring le faire automatiquement. Sa déclaration make septate de haricot de la définition de classe.
  • En bref, @Controller, @service, @repository sont destinés à la détection automatique et @Bean pour créer un bean seprate de la classe
 - @Manette
 Classe publique LoginController 
 {--code--} 

 - @Configuration
 Classe publique AppConfig {
 @Haricot
 public SessionFactory sessionFactory () 
 {--code--} 
3
alok

@Bean a été créé pour éviter le couplage de Spring et de vos règles métier lors de la compilation. Cela signifie que vous pouvez réutiliser vos règles métier dans d'autres frameworks tels que PlayFramework ou JEE.

De plus, vous avez un contrôle total sur la manière de créer des haricots, où l’instantation Spring par défaut ne suffit pas.

J'ai écrit un post en parlant.

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

Je vois beaucoup de réponses et presque partout, son @Component mentionné est destiné au câblage automatique où le composant est analysé et @Bean est exactement déclarant que ce bean est utilisé différemment. Laissez-moi vous montrer en quoi c'est différent.

  • @Haricot

Tout d'abord, c'est une annotation au niveau de la méthode. Deuxièmement, vous utilisez généralement pour configurer les beans dans un code Java (si vous n’utilisez pas la configuration xml), puis vous l’appelez depuis une classe en utilisant la méthode getBean de ApplicationContext. comme

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

class User{
}



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

C'est un moyen général d'annoter un haricot et non un haricot spécialisé. Une annotation au niveau de la classe est utilisée pour éviter tout ce genre de configuration via la configuration Java ou XML.

Nous obtenons quelque chose comme ça.

@Component
class User {
}

//to get Bean
@Autowired
User user;

C'est tout . Il a été simplement introduit pour éviter toutes les étapes de configuration pour instancier et utiliser ce bean.

2
xpioneer

Vous avez deux façons de générer des haricots. L'une consiste à créer une classe avec une annotation @Component. L'autre consiste à créer une méthode et à l'annoter avec @Bean. Pour les classes contenant une méthode avec @Bean, annotez-le avec @Configuration Une fois que vous avez exécuté votre projet Spring, la classe avec une annotation @ComponentScan analysera chaque classe avec @Component et restaurera l'instance de cette classe dans le conteneur Ioc. Une autre chose que @ComponentScan ferait serait d'exécuter les méthodes avec @Bean dessus et de restaurer l'objet de retour dans le conteneur Ioc en tant que bean . Ainsi, lorsque vous devez choisir le type de haricots que vous souhaitez créer en fonction des états actuels, vous devez utiliser @Bean. Vous pouvez écrire la logique et retourner l'objet que vous voulez . Une autre chose à noter est le nom de la méthode avec @Bean étant le nom par défaut de bean.

1
Dai Niu