1. @Service sur les interfaces
@Service
public interface AuthenticationService {
boolean authenticate(String username, String password);
}
Normalement, c'est bien, mais il y a un inconvénient. En mettant la méthode de Spring @Service
sur les interfaces, nous créons une dépendance supplémentaire et couplons nos interfaces avec une bibliothèque extérieure.
Ensuite, pour tester l'autodétection de nos nouveaux beans de service, créons une implémentation de notre module AuthenticationService
:
public class InMemoryAuthenticationService implements AuthenticationService {
@Override
public boolean authenticate(String username, String password) {
//...
}
}
Nous devons faire attention à notre nouvelle mise en œuvre, InMemoryAuthenticationService
n'a pas le @Service
sur celui-ci. Nous avons laissé @Service
uniquement sur l'interface, AuthenticationService
.
Donc, exécutons notre contexte Spring à l'aide d'une configuration de base de Spring Boot :
@SpringBootApplication
public class AuthApplication {
@Autowired
private AuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
Lorsque nous lançons notre application, nous pouvons obtenir l'infâme NoSuchBeanDefinitionException et le contexte Spring ne démarre pas.
Par conséquent, le fait de placer @Service
sur les interfaces n'est pas suffisant pour l'auto-détection des composants Spring.
2. @Service sur les classes abstraites
Utilisation de la @Service
sur les classes abstraites n'est pas courante.
Nous commencerons par définir une classe abstraite en partant de zéro et en mettant l'élément @Service
sur celui-ci :
@Service
public abstract class AbstractAuthenticationService {
public boolean authenticate(String username, String password) {
return false;
}
}
Ensuite, nous étendons AbstractAuthenticationService
pour créer une implémentation concrète sans l'annoter :
public class LdapAuthenticationService extends AbstractAuthenticationService {
@Override
public boolean authenticate(String username, String password) {
//...
}
}
Par conséquent, nous mettons également à jour notre AuthApplication
pour injecter la nouvelle classe de service :
@SpringBootApplication
public class AuthApplication {
@Autowired
private AbstractAuthenticationService authService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
Après avoir exécuté notre AuthApplication
le contexte du printemps ne démarre pas. Il se retrouve avec le même NoSuchBeanDefinitionException Encore une exception.
Ainsi, en utilisant @Service
sur les classes abstraites n'a pas d'effet dans Spring.
3. @Service sur les classes concrètes
Contrairement à ce que nous avons vu ci-dessus, il est assez courant d'annoter les classes d'implémentation plutôt que les classes abstraites ou les interfaces.
De cette façon, notre but est surtout de dire à Spring que cette classe va être une @Component
et le marquer avec un stéréotype spécial, qui est @Service
dans notre cas.
Par conséquent, Spring va autodétecter ces classes à partir du classpath et les définir automatiquement comme des beans gérés.
Alors, mettons @Service
sur nos classes de service en béton cette fois-ci. Nous aurons une classe qui implémente notre interface et une seconde qui étend la classe abstraite que nous avons définie précédemment :
@Service
public class InMemoryAuthenticationService implements AuthenticationService {
@Override
public boolean authenticate(String username, String password) {
//...
}
}
@Service
public class LdapAuthenticationService extends AbstractAuthenticationService {
@Override
public boolean authenticate(String username, String password) {
//...
}
}
Nous devons noter ici que notre AbstractAuthenticationService
n'implémente pas le AuthenticationService
ici. Ainsi, nous pouvons les tester indépendamment.
Enfin, nous ajoutons nos deux classes de service dans le répertoire de l'utilisateur. AuthApplication
et faire un essai :
@SpringBootApplication
public class AuthApplication {
@Autowired
private AuthenticationService inMemoryAuthService;
@Autowired
private AbstractAuthenticationService ldapAuthService;
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
Notre test final nous donne un résultat positif, et le contexte Spring démarre sans exception. Les deux services sont automatiquement enregistrés en tant que beans.
Pour des explications complètes, vous pouvez consulter les sites suivants Où doit-on conserver l'annotation Spring @Service ? par Yavuz Taş.