web-dev-qa-db-fra.com

Où les annotations @Service doivent-elles être conservées? Interface ou mise en œuvre?

Je développe une application en utilisant Spring. Je suis obligé d'utiliser l'annotation @Service. J'ai ServiceI et ServiceImpl tels que ServiceImpl implements ServiceI. Je ne comprends pas trop où devrais-je conserver l'annotation @Service.

Dois-je annoter l'interface ou l'implémentation avec @Service? Quelles sont les différences entre ces deux approches?

82
TheKojuEffect

En gros, les annotations telles que @Service , @Repository , @Component , etc. servent toutes le même objectif: 

détection automatique lors de l'utilisation d'une configuration et d'un classpath basés sur des annotations balayage.

D'après mon expérience, j'utilise toujours l'annotation @Service sur les interfaces ou des classes abstraites et des annotations telles que @Component et @Repository pour leur implémentation. @Component annotation que j'utilise sur ces classes qui sert des objectifs de base, de simples haricots Spring, rien de plus. @Repository annotation que j'utilise dans la couche DAO, par exemple. si je dois communiquer avec la base de données, effectuer des transactions, etc.

Je suggère donc d’annoter votre interface avec le @Service et d’autres couches en fonction de la fonctionnalité.

30

Je n'ai jamais mis @Component (ou @Service, ...) à une interface, car cela rend l'interface inutile. Laisse moi expliquer pourquoi.

claim 1: Si vous avez une interface, vous voulez utiliser cette interface pour le type de point d'injection.

claim 2: Le but d'une interface est de définir un contrat pouvant être mis en oeuvre par plusieurs implémentations. De l'autre côté, vous avez votre point d'injection (@Autowired). Avoir une seule interface et une seule classe qui l'implémente est (IMHO) inutile et viole YAGNI .

fait: Quand vous mettez:

  • @Component (ou @Service, ...) à une interface,
  • avoir plusieurs classes qui l'implémente,
  • au moins deux classes deviennent des haricots de printemps, et
  • avoir un point d'injection utilisant l'interface pour l'injection basée sur le type, 

alors vous obtiendrez une NoUniqueBeanDefinitionException (ou vous avez une configuration très spéciale, avec Environment, Profiles ou Qualifiers ...) 

Conclusion: Si vous utilisez @Component (ou @Service, ...) à une interface, vous devez violer au moins une des deux bases. Par conséquent, je pense qu'il n'est pas utile (sauf quelques scénarios rares) de mettre @Component au niveau de l'interface.


_ {Les interfaces du référentiel Spring-Data-JPA sont complètement différentes les unes des autres}

85
Ralph

J'ai utilisé les annotations @Component, @Service, @Controller et @Repository uniquement sur les classes d'implémentation et non sur l'interface. Mais l'annotation @Autowired avec les interfaces fonctionnait toujours pour moi. 

11
yalkris

L’avantage de mettre une annotation sur @Service est que cela donne à penser que c’est un service. Je ne sais pas si une classe d'implémentation héritera par défaut de cette annotation.

Le côté inconvénient, c’est que vous couplez votre interface avec un cadre spécifique, c’est-à-dire Spring, en utilisant l’annotation spécifique au ressort . Étant donné que les interfaces sont censées être découplées de la mise en œuvre, je ne suggérerais pas d'utiliser d'annotations spécifiques au framework ni de partie objet de votre interface.

5
Kuldeep Tiwari

Un avantage de spring est de changer facilement d’implémentation Service (ou autre) . Pour cela, vous devez annoter sur l’interface et déclarer une variable comme ceci:

@Autowired
private MyInterface myVariable;

et pas :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

Comme dans le premier cas, vous pouvez activer quelle implémentation injecter à partir du moment où elle est unique (une seule classe implémente l'interface) . Dans le deuxième cas, vous devez refactoriser tout votre code (la nouvelle implémentation de classe a un autre nom ) . En conséquence, l'annotation doit figurer autant que possible sur l'interface. De plus, les proxies JDK sont bien adaptés à cela: ils sont créés et instanciés au démarrage de l'application car le type d'exécution est connu d'avance, contrairement aux proxies CGlib.

1
François F.

Pour le dire simplement:

@Service est une annotation de stéréotype pour la couche service .

@Repository est une annotation de stéréotype pour la couche persistence .

@Component est une annotation generic stéréotype utilisée pour indiquer à Spring de créer une instance de l'objet dans le contexte d'application. Il est possible de définir un nom quelconque pour l'instance, la valeur par défaut est le nom de la classe comme cas de chameau.

0
HughParker