4 votes

Obtenir la classe réelle utilisée pour une MethodInvocation plutôt que la classe déclarante

Je suis en train de fouiller dans une application web pour tenter de résoudre certains problèmes. L'application utilise Tomcat, Jersey et Guice. L'un des problèmes se produit dans un MethodInterceptor utilisé à des fins d'autorisation. Voici la méthode, coupée à la partie pertinente :

public Object invoke(MethodInvocation invoc) throws Throwable {
    // ...

    //Check that the annotation actually exists
    if(! invoc.getMethod().getDeclaringClass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

    // ...
}

Le problème est que certaines des méthodes "web-facing" sont héritées d'une classe parent sans être surchargées dans la classe enfant. Si je comprends bien la méthode getDeclaringClass(), elle renvoie la méthode parent dans ce cas, mais ce que nous voulons vraiment ici est la classe enfant. Certains tests semblent le confirmer : si je surcharge la méthode dans la classe enfant, tout va bien, mais si je ne mets pas la surcharge, une exception est levée.

Ainsi, étant donné un objet MethodInvocation, existe-t-il un moyen de remonter à la classe "réelle" instanciée, plutôt qu'à la classe où la méthode a été déclarée ? Ou une autre approche est-elle nécessaire ? Dans le pire des cas, je pourrais juste annoter chaque méthode comme nécessaire plutôt que d'annoter la classe.

Désolé si c'est une question longue pour une réponse facile - mon Java est assez rouillé.

8voto

Smashd Points 841

Assez simple, nécessaire à utiliser getThis().getClass() sur la MethodInvocation au lieu de getMethod().getDeclaringClass() :

    if(! invoc.getThis().getClass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

Bien que dans mon cas, Guice ait un peu compliqué les choses en mettant une classe enfant générée automatiquement (par exemple, un nom de classe se terminant par "$$EnhancerByGuice...". Cela a été corrigé en déplaçant une classe vers le haut de l'arbre avec getSuperclass() :

    if(! invoc.getThis().getClass().getSuperclass().isAnnotationPresent(Tool.class))
    {
        throw new BaseException("...");
    }

0voto

BrownFurSeal Points 515

Il semble que la réponse soit non. J'ai créé un test simple pour le vérifier :

    class Run implements Runnable {
        @Override
        public void run() {
        }
    }
    class Run2 extends Run{}
    Method method = Run2.class.getMethods()[0];
    System.out.println(method);

Comme nous pouvons le voir dans la fenêtre de débogage, la méthode n'a aucune information sur la classe Run2 :

Method in debug window

Je pense qu'il serait préférable de s'en tenir aux méthodes réelles avec leurs annotations plutôt qu'aux instances de classe réelles où ces méthodes sont invoquées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X