Sorti en 2003, Spring est un framework libre, créé pour faciliter le développement et les tests d'applications Java.
Spring s’appuie principalement sur l’intégration de 3 concepts clés :
L’inversion de contrôle est assurée de deux façons différentes :
La programmation orientée aspect.
Une couche d’abstraction : elle permet d’intégrer d’autres frameworks et bibliothèques avec une plus grande facilité.
Spring utilise un système de Bean. Un Bean est un objet qui est instancié, assemblé et géré par Spring IoC Container.
IoC (Inversion of control), est un processus qui définit les dépendances d’un objet sans avoir à les créer. C’est lors de la création des objets, que Spring va injecter les Beans entre eux afin d’avoir toutes leurs dépendances.
Le cycle de vie d’un Bean est assez simple : il est instancié et rajouté au container lorsqu’il doit être utilisé, et détruit lorsque le container est détruit.
Pour aider à leur configuration, il existe 2 méthodes qui sont utilisées à la création et à la destruction d’un Bean.
La méthode d’initialisation est appelée immédiatement lors de l’instanciation, et la méthode de destruction juste avant que le Bean ne soit supprimé du container.
L’interface org.springframework.beans.factory.InitializingBean spécifie une seule méthode :
void afterPropertiesSet() throws Exception;
De ce fait, il suffit d’implémenter l’interface ci-dessus, et la logique d’initialisation sera faite dans afterPropertierSet()
public class ExampleBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
// do some initialization work
}
}
Vous pouvez également utiliser l’annotation @PostConstruct
public class ExampleBean {
@PostConstruct
public void init() {
// do some initialization work
}
}
L’interface _org.springframework.beans.factory.DisposableBean spécifie une seule méthode :
void destroy() throws Exception;
De ce fait, il suffit d’implémenter l’interface ci-dessus, et la logique d’avant destruction sera faite dans destroy()
public class ExampleBean implements DisposableBean {
@Override
public void destroy() {
// do some destroy work
}
}
Vous pouvez également utiliser l’annotation @PreDestroy
public class ExampleBean {
@PreDestroy
public void init() {
// do some initialization work
}
}
Une configuration de Bean peut être faite de deux manières différentes : XML ou annotations.
Seule la partie annotations sera abordée ici.
Spring scanne toutes les classes. Dès lors qu’il trouve une annotation @Component, il l’enregistre automatiquement en tant que Bean.
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl {
}
Il est possible de définir le scope d’un Bean grâce à l'annotation @Scope.
Spring supporte 5 types de scopes, 3 d’entre eux ne sont valables que pour les applications Web.
Le scope par défaut est «;singleton;».
@Component
@Scope("prototype")
public class UserServiceImpl {
}
L’injection d’un Bean peut être faite de plusieurs manières :
Grace à l'annotation @Autowired, le Bean va être simplement injecté :
@Component
public class App {
@Autowired
private UserServiceImpl userService;
public App(){
}
}
En incluant le Bean dans le constructeur d’une classe :
@Component
public class App {
private final UserServiceImpl userService;
public App(UserServiceImpl pUserService){
this.userService = pUserService ;
}
}
Une grande puissance de Spring est l’utilisation d’interface pour l’injection de Bean.
Il est possible d'utiliser une interface, Spring va ensuite se charger d’utiliser la bonne implémentation de l’interface comme Bean.
public interface UserService {
User getUser(String userName);
boolean createUser(User user);
}
@Component
public class UserServiceAdminImpl implements UserService {
@Override
User getUser(String userName){
// do smthg
}
@Override
boolean createUser(User user){
// do smthg
}
}
@Component
public class UserServiceReaderImpl implements UserService {
@Override
User getUser(String userName){
// do smthg else
}
@Override
boolean createUser(User user){
// do smthg else
}
}
Par défaut, s’il n’y a qu’une seule implémentation d’une interface, l'implémentation en question sera injectée.
Sinon, vous pouvez utiliser l’annotation @Qualifier(« bean-id« ) afin de choisir quelle implémentation utiliser.
@Component
public class App {
@Qualifier(« userServiceAdminImpl »)
private final UserService userService;
public App(UserServiceImpl pUserService){
this.userService = pUserService ;
}
}
Il est également possible de déclarer un Bean directement grâce à une méthode.
Avec l’annotation @Bean sur une méthode, Spring va exécuter la méthode et enregistrer la valeur du return en tant que Bean.
À noter qu'il faut l'annotation @Configuration sur la classe qui contient les @Bean, afin d'indiquer à Spring que, lors du scan, il y a des Beans dans cette classe.
@Configuration
public class UserServiceImpl {
@Bean(name = "userService")
public UserService userAdminService()
return new UserService() {
@Override
User getUser(String userName){
// do smthg
}
@Override
boolean createUser(User user){
// do smthg
}
}
}
@Component
public class App {
@Autowired
private final UserService userService;
public App(){
}
}
L’exemple ci-dessus a le même comportement que l'exemple précédent, seule la syntaxe est différente.
Utilisé avec des @Conditional, cela permet d’avoir des applications hautement configurables simplement et sans avoir des classes de partout !
Nous verrons les @Conditional dans un prochain article !
Java 9, quelques méthodes utiles pour la gestion des strings
Qu’est-ce qu’un agent de message ou message broker ? À quoi ça sert ? Quels outils : plutôt Apache Kafka ou Rabbit MQ ? Le point avec des exemples sur cet article !
```