• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Fresque numérique miniature image
Fresque du Numérique
16 avril 2025
Ressources > Articles techniques > Annotations Spring Boot peu connues mais pratiques

Annotations Spring Boot peu connues mais pratiques

Écrit par Thusitha T.

En général, on a souvent tendance à associer Spring Boot aux annotations célèbres comme @RestController, @Service ou @Autowired. Pourtant, Spring Boot offre un large éventail d’autres annotations, souvent moins connues mais tout aussi utiles permettant d’optimiser le développement et améliorer la maintenabilité du code. Dans cet article, nous allons explorer certaines de ces annotations avec un exemple de code.

ConditionalOnProperty

En utilisant l’annotation @ConditionalOnProperty, nous pouvons activer ou désactiver un bean selon la valeur ou l’existence d’une propriété dans le fichier de configuration. Elle peut être très pratique pour ajuster certaines fonctionnalités en fonction de l’environnement.

@Configuration
public class FeatureConfig {

    @Bean
    @ConditionalOnProperty(name = "featureX.enabled", havingValue = "true")
    public FeatureXService featureXService() {
        return new FeatureXService();
    }
}

Dans le fichier application.properties nous aurons donc :

featureX.enabled=true

ConditionalOnMissingBean

@ConditionalOnMissingBean va nous permettre de déclarer un bean par défaut s’il n’existe pas déjà une autre définition du même type. Cela peut être très utile dans le cas où nous avons un projet Socle qui doit définir une implémentation par défaut mais qui doit être remplaçable par un projet qui l’utilise et qui veut la surcharger.

@Configuration
public class DefaultServiceConfig {

    @Bean
    @ConditionalOnMissingBean
    public UserService defaultUserService() {
        return new DefaultUserService();
    }
}

Async

Il peut arriver très souvent que nous ayons besoin de lancer un traitement asynchrone. C’est là que l’annotation @Async vient nous aider car en l’utilisant, Spring Boot va prendre en charge la création d’un thread pour exécuter la méthode en arrière-plan sans bloquer le thread principal.

@Service
public class EmailService {

    @Async
    public void sendEmail(String recipient) {
        // Simuler un envoi d'email avec un délai
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Email envoyé à " + recipient);
    }
}

Pour activer cette fonctionnalité, il suffira d’ajouter l’annotation @EnableAsync :

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Profile

L’annotation @Profile va nous permettre d’activer des beans ou des configurations uniquement dans certains environnements. Ainsi, en se basant sur le paramètre spring.profiles.active=dev, il nous sera par exemple possible d’activer une fonctionnalité seulement en dev.

@Configuration
@Profile("dev")
public class DevDatabaseConfig {

    @Bean
    public DataSource dataSource() {
        return new DevDataSource();
    }
}

Retryable

Même si ce n’est pas l’idéal, il est possible que dans le cadre de notre projet, nous ayons besoin par exemple d’appeler une API externe qui peut parfois échouer. Dans ce cas, @Retryable sera notre solution car elle va permettre de réessayer automatiquement l’exécution d’une méthode en cas d’échec.

@Service
public class ApiService {

    @Retryable(value = { RemoteServiceException.class }, maxAttempts = 3)
    public String callRemoteService() {
        // Simuler un appel à un service distant
        throw new RemoteServiceException("Erreur d'appel au service distant");
    }
}

Cette annotation va nous permettre, entre autre de renseigner :

  • value qui est l’exception qui va relancer la méthode. Nous pouvons fournir une liste d’execptions également.
  • maxAttempts permettant d’indiquer le nombre de tentatives total. Si après 3 tentatives l’erreur persiste, l’exception sera levée définitivement et non rattrapée par la logique de retry.

Recover

En complément de l’annotation @Retryable, @Recover va nous permettre de définir une méthode de “récupération” qui sera appelée après que toutes les tentatives de retry aient échoué nous permettant ainsi d’effectuer une action alternative ou de retourner une valeur de secours.

@Service
public class ApiService {

    @Retryable(value = { RemoteServiceException.class }, maxAttempts = 3)
    public String callRemoteService() {
        // Simuler un appel à un service distant
        throw new RemoteServiceException("Erreur d'appel au service distant");
    }

    @Recover
    public String recover(RemoteServiceException e) {
        // Action alternative après échec de toutes les tentatives
        return "Service indisponible pour le moment, veuillez réessayer plus tard.";
    }
}

Cacheable

Nous avons souvent des données référentielles qui peuvent être stockées dans la BDD du projet. Il peut être dommage d’interroger la BDD à chaque demande étant donné que les valeurs retournées seront toujours identiques. L’annotation @Cacheable va nous permettre de mettre en cache le résultat d’une méthode pour éviter de recalculer une même valeur à chaque appel. Ainsi, la prochaine fois que la même méthode sera appelée, le résultat sera récupérée depuis le cache.

@Service
public class ProductService {

    @Cacheable("products")
    public List<Product> findProducts() {
        // Simuler un appel à une base de données ou à un service distant
        List<Product> products = new ArrayList<>();
        products.add(new Product(1L, "Produit 1"));
        products.add(new Product(2L, "Produit 2"));
        products.add(new Product(3L, "Produit 3"));
        return products;
    }
}

Par défaut, l’annotation @Cacheable met en cache les données indéfiniment. Cependant, il peut être parfois utile de configurer un temps d’expiration pour garantir que les données restent à jour. Pour ce faire, il suffit d’ajouter quelques dépendances dans le fichier pom.xml et de créer un fichier de configuration pour le cache.

pom.xml :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

ehcache.xml (dans le dossier resources) :

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.ehcache.org/v3"
        xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd">

    <cache alias="products">
        <expiry>
            <ttl unit="minutes">10</ttl> <!-- Expiration après 10 minutes -->
        </expiry>
        <resources>
            <heap>100</heap> <!-- Limite de 100 objets en cache -->
        </resources>
    </cache>
</config>

Conclusion

En tant que développeurs, nous savons que le cadre Spring Boot est si vaste que nous ne connaissons pas toutes les annotations qui peuvent nous faciliter la vie. Parmi celles-ci, certaines sont souvent sous-estimées, telles que @ConditionalOnProperty, @Async et @Retryable, qui offrent des solutions simples à des problèmes complexes tout en ayant moins de code à écrire. En les intégrant dans nos projets, nous pouvons ainsi augmenter l’efficacité tout en ayant un code propre et plus maintenable.

Pour les plus curieux

  • The Spring @ConditionalOnProperty Annotation
  • Annotation Interface ConditionalOnMissingBean
  • How To Do @Async in Spring
  • Spring Profiles
  • Retry Mechanism in Spring Boot(@Retryable and @Recover)
  • A Guide To Caching in Spring

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter