Initialisation du conteneur SpringMVC avec l'interface ApplicationListener de Spring

Dans les applications SpringMVC, l'initialisation du conteneur est généralement configurée via le fichier web.xml. Cependant, pour des besoins de test ou de flexibilité, il peut être pratique de charger directement le fichier de configuration Spring-MVC. L'utilisation de l'interface ApplicationListener de Spring offre une méthode élégante pour exécuter des tâches d'initialisation après le chargement complet du conteneur, en tirant parti des annotations sans impacter le code métier.

L'événement ContextRefreshedEvent est déclenché lorsque le conteneur d'application Spring a fini de charger tous les beans. En implémentant l'interface ApplicationListener pour cet événement, nous pouvons définir une logique d'initialisation personnalisée. Il est important de vérifier que le contexte n'a pas de parenet afin d'éviter des exécutions multiples en cas de hiérarchie de conteneurs.

Voici un exemple de classe écouteur :

package fr.demo.init;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class EcouteurInitialisation implements ApplicationListener<ContextRefreshedEvent> {
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent evenement) {
        if (evenement.getApplicationContext().getParent() == null) {
            // Logique d'initialisation à exécuter une seule fois
            System.out.println("Le conteneur Spring est prêt : lancement des routines de démarrage.");
        }
    }
}

Pour enregistrer cet écouteur dans le conteneur Spring, ajoutez la déclaration suivante dans votre fichier de configuration XML :

<bean class="fr.demo.init.EcouteurInitialisation"/>

Cette approche est particulièrement utile pour des tâches telles que l'initialisation de connexions à la base de données, le préchargement de configurations ou la mise en place de caches. Elle évite d'avoir à implémenter manuellement ces opérations dans des servlets.

Lorsque l'on a besoin d'accéder à d'autres beans du conteneur (comme des services ou des contrôleurs) au sein de l'écouteur, il est nécessaire de récupérer l'ApplicationContext. Une méthode consiste à étendre la classe ApplicationObjectSupport, comme illustré ci-dessous :

package fr.demo.init;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.ApplicationObjectSupport;

public class EcouteurAvance extends ApplicationObjectSupport implements ApplicationListener<ContextRefreshedEvent> {
    private static ApplicationContext contexteApp = null;
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent evenement) {
        if (evenement.getApplicationContext().getParent() == null) {
            // Exemple d'utilisation d'un bean récupéré
            // Object service = getBean("idService");
            System.out.println("Exécution de l'initialisation avancée avec accès aux beans.");
        }
    }
    
    @Override
    protected void initApplicationContext(ApplicationContext context) throws BeansException {
        super.initApplicationContext(context);
        if (contexteApp == null) {
            contexteApp = context;
        }
    }
    
    public static ApplicationContext obtenirContexte() {
        return contexteApp;
    }
    
    public static Object getBean(String idBean) {
        return obtenirContexte().getBean(idBean);
    }
}

Dans les configurations utilisant à la fois un fichier application.xml et un fichier de configuration spécifique au projet (comme project-servlet.xml), un problème de double appel peut survenir à cause de la hiérarchie des conteneurs. Pour éviter cela, ajoutez une condition de retour anticipé dans la méthode onApplicationEvent :

if (evenement.getApplicationContext().getParent() != null) {
    return; // Ignorer les événements des conteneurs enfants
}

Ainsi, seule l'initialisation du conteneur parent (celui sans parent) déclenchera les opérations d'initialisation souhaitées.

Étiquettes: Spring SpringMVC ApplicationListener Java Initialisation de conteneur

Publié le 24 juin à 21h39