3

Parfois, les interfaces sont annotées avec l'annotation @Component. Ensuite, mon raisonnement évident était que les classes qui implémentent une telle interface seront également traitées comme des composants. Mais si j'ai raison, ce n'est pas le cas.Les annotations sont annotées avec l'annotation @Component au printemps IoC/DI. Quelle pourrait être la raison?

Alors, quel est le but de l'annotation @Component sur les interfaces.

+0

* "Mais si j'ai raison, ce n'est pas le cas." * - Pourquoi supposez-vous cela? – Tom

+0

Quoi qu'il en soit, j'ai testé la même chose. i.e Spring n'est pas capable de détecter et d'autowire les classes qui implémentent une telle interface.Je devais ajouter explicitement l'annotation '@ Component' sur les classes. – samshers

+1

"Parfois, les interfaces sont annotées avec l'annotation @Component." Pouvez-vous donner un exemple concret? – davidxxx

Répondre

3

Annoter une interface avec @Component est commun pour les classes de printemps, en particulier pour certaines annotations stéréotypes de printemps:

package org.springframework.stereotype; 
... 
@Component 
public @interface Service {...} 

ou:

package org.springframework.boot.test.context; 
... 
@Component 
public @interface TestComponent {...} 

@Component est pas déclarée comme une annotation héritée:

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Component {...} 

Mais peu importe, pendant En chargeant le contexte, Spring découvre les beans en considérant la hiérarchie de l'annotation déclarée dans la classe candidate.

Dans la org.springframework.boot.BeanDefinitionLoader classe (inclus dans la dépendance de démarrage du printemps) qui charge les définitions de haricots de sources sous-jacentes, vous pouvez voir un exemple de org.springframework.core.annotation.AnnotationUtils.findAnnotation() que Spring utilise pour récupérer des annotations dans toute la hiérarchie de l'annotation:

class BeanDefinitionLoader { 
... 
private boolean isComponent(Class<?> type) { 
    // This has to be a bit of a guess. The only way to be sure that this type is 
    // eligible is to make a bean definition out of it and try to instantiate it. 
    if (AnnotationUtils.findAnnotation(type, Component.class) != null) { 
     return true; 
    } 
    // Nested anonymous classes are not eligible for registration, nor are groovy 
    // closures 
    if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass() 
      || type.getConstructors() == null || type.getConstructors().length == 0) { 
     return false; 
    } 
    return true; 
} 
... 
} 

Concrètement, cela signifie que l'annotation @Service lui-même est annoté avec @Component, Spring examinera une classe candidat annotée avec @Service comme un haricot à instancier.

Ainsi, votre devinettes est droite:

Les classes qui implémentent cette interface seront traités comme des composants aussi bien .

Mais cela ne fonctionne que pour les interfaces (telles que @Service) qui sont des annotations Java et non pas pour les interfaces simples.

Pour les classes de printemps, cette façon de faire est logique (enrichissement stéréotype réel par exemple), mais pour vos propres haricots, en utilisant @Component pour l'interface plutôt que la mise en œuvre ne fonctionnera pas et apporterait plus d'inconvénients que d'avantages:

  • il défait de la même manière le but d'une interface qui est avant tout un contrat. Il le couple au printemps et il suppose que vous aurez toujours une seule implémentation de la classe.
    Dans ce cas, pourquoi utiliser une interface?

  • il disperse la lecture de la classe à deux endroits alors que l'interface n'a pas besoin d'avoir de stéréotype Spring.