0Pricing
Java Academy · Leçon

Proxys dynamiques avec InvocationHandler

Créez des proxys dynamiques JDK pour intercepter les appels de méthodes d’interface à des fins de journalisation, de mise en cache et de nouvelle tentative.

Proxys dynamiques avec InvocationHandler est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Qu’est-ce qu’un proxy dynamique ?

Un proxy dynamique JDK est un objet créé à l’exécution qui implémente une ou plusieurs interfaces. Tous les appels de méthode sont transmis à un InvocationHandler que vous fournissez.

Créer un proxy avec Proxy.newProxyInstance

Appelez Proxy.newProxyInstance(classLoader, interfaces[], handler) pour créer un proxy. Celui-ci implémente toutes les interfaces indiquées.

UserService proxy = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    new LoggingHandler(realService)
);
proxy.findById(42L); // intercepted by LoggingHandler

L’interface InvocationHandler

Implémentez InvocationHandler pour gérer chaque appel de méthode. Le gestionnaire reçoit l’objet proxy, la méthode appelée et les arguments.

public class LoggingHandler implements InvocationHandler {
    private final Object target;
    public LoggingHandler(Object target) { this.target = target; }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(">> " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("<< " + method.getName());
        return result;
    }
}

Proxy pour la mise en cache

Un InvocationHandler peut mettre les résultats en cache : si le cache contient un résultat correspondant aux arguments, renvoyez-le ; sinon, appelez la méthode réelle et enregistrez le résultat.

public class CachingHandler implements InvocationHandler {
    private final Object target;
    private final Map<String, Object> cache = new HashMap<>();
    public CachingHandler(Object target) { this.target = target; }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String key = method.getName() + Arrays.toString(args);
        return cache.computeIfAbsent(key, k -> {
            try { return method.invoke(target, args); }
            catch (Exception e) { throw new RuntimeException(e); }
        });
    }
}

Proxy pour la logique de nouvelle tentative

Encapsulez les appels de méthode dans une boucle de nouvelle tentative. Si une exception se produit, réessayez jusqu’à N fois avant de la relancer.

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    for (int attempt = 1; attempt <= 3; attempt++) {
        try { return method.invoke(target, args); }
        catch (InvocationTargetException e) {
            if (attempt == 3) throw e.getCause();
            Thread.sleep(1000L * attempt);
        }
    }
    throw new RuntimeException("unreachable");
}

Proxy pour la gestion des transactions

@Transactional de Spring utilise un proxy dynamique pour démarrer une transaction avant un appel de méthode, puis la valider ou l’annuler après — tout cela à l’insu de l’appelant.

Vérifier si un objet est un proxy

Utilisez Proxy.isProxyClass(obj.getClass()) pour détecter les proxys et Proxy.getInvocationHandler(proxy) pour récupérer le gestionnaire.

if (Proxy.isProxyClass(service.getClass())) {
    InvocationHandler h = Proxy.getInvocationHandler(service);
    System.out.println("Handler: " + h.getClass().getSimpleName());
}

Limites des proxys dynamiques JDK

Les proxys dynamiques JDK fonctionnent uniquement avec les interfaces — ils ne peuvent pas servir de proxy pour des classes concrètes. Pour créer un proxy fondé sur une classe, utilisez CGLIB, que Spring utilise également en interne pour les classes @Configuration.

CGLIB comme alternative

CGLIB génère à l’exécution une sous-classe de la classe cible, qui redéfinit toutes les méthodes non finales. Spring l’utilise lorsqu’aucune interface n’est présente. Aucune annotation n’est nécessaire — son fonctionnement est transparent.

Les proxys dans Hibernate

Hibernate charge paresseusement les associations d’entités à l’aide de proxys CGLIB/Byte Buddy. Lorsque vous accédez à une collection chargée paresseusement, le proxy lance une requête SQL.

// Hibernate creates a proxy for:
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
// Accessing dept triggers a DB query via the proxy

Performances des proxys

La répartition des appels de méthode par un proxy dynamique est environ 5 à 10 fois plus lente qu’un appel direct. Pour les chemins très sollicités, envisagez la génération de code à la compilation (APT) ou MethodHandles plutôt que les proxys dynamiques.

Vérification rapide

Quelle est la principale limite des proxys dynamiques JDK ?

Récapitulatif

Les proxys dynamiques JDK interceptent les appels de méthodes d’interface via InvocationHandler. Utilisez-les pour la journalisation, la mise en cache, les nouvelles tentatives et la gestion des transactions. Pour créer un proxy de classe, utilisez CGLIB. Mettez la création des proxys en cache — elle repose sur la réflexion et n’est pas gratuite.

Questions Fréquemment Posées

La leçon « Proxys dynamiques avec InvocationHandler » est-elle gratuite ?

Oui — le texte complet de « Proxys dynamiques avec InvocationHandler » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Proxys dynamiques avec InvocationHandler » ?

Créez des proxys dynamiques JDK pour intercepter les appels de méthodes d’interface à des fins de journalisation, de mise en cache et de nouvelle tentative. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Proxys dynamiques avec InvocationHandler » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Inspection des classes avec la réflexion
  2. Appeler des méthodes et accéder aux champs
  3. Proxys dynamiques avec InvocationHandler
  4. Performances de la réflexion et solutions de remplacement
← Retour à Java Academy