2010-05-10 4 views
1

Supposons que vous ayez une interface générique et une mise en œuvre:Comment trouver la première méthode pour déclarer une méthode de référence

public interface MyInterface<T> { 

    void foo(T param); 
} 

public class MyImplementation<T> implements MyInterface<T> { 

    void foo(T param) { 

    } 
} 

Ces deux types sont des types de cadre que je propose. Dans la prochaine étape, je veux permettre aux utilisateurs d'étendre cette interface ainsi que redéclarer foo(T param) pour peut-être l'équiper avec d'autres annotations. Je crée un proxy AOP pour l'interface étendue et intercepte en particulier les appels à des méthodes déclarées plus loin. Comme foo(…) est maintenant redéclaré dans MyExtendedInterface Je ne peux pas l'exécuter en appelant simplement MethodInvocation.proceed() car l'instance de MyImplementation implémente seulement MyInterface.foo(…) et non MyExtendedInterface.foo(…).

Y a-t-il un moyen d'accéder à la méthode qui a déclaré une méthode initialement? En ce qui concerne cet exemple est-il un moyen de savoir que foo(Bar param) a été déclaré dans MyInterface à l'origine et avoir accès à l'instance Method accoriding? J'ai déjà essayé d'analyser les méthodes de classe de base pour faire correspondre par nom et les types de paramètres, mais cela ne fonctionne pas comme génériques pop et MyImplementation.getMethod("foo", Bar.class) jette évidemment NoSuchMethodException. Je sais déjà que MyExtendedInterface types MyInterface à Bar. Donc, si je pouvais créer une sorte de "vue typée" sur MyImplementation mon algorithme de maths pourrait fonctionner réellement.

Informations complémentaires:

je crée le proxy pour le MyExtendedInterface comme suit:

ProxyFactory factory = new ProxyFactory(); 
factory.setTarget(new MyImplementation()); 
factory.setInterfaces(new Class[] { MyExtendedInterface.class }); 
factory.addInterceptor(new MyInterceptor(MyExtendedInterface.class)); 

L'intercepteur assez balaye beaucoup les méthodes et exécute des requêtes JPA pour toutes les méthodes déclarées dans MyExtendedInterface mais les routes toutes les invocations de méthode des méthodes déclarées dans MyInterface à la cible proxy. Cela fonctionne tant que les méthodes de MyInterface ne sont pas redéclarées comme cible, puis ne l'implémentent plus.

public class MyInterceptor implements MethodInterceptor { 

    public Object invoke(final MethodInvocation invocation) 
      throws Throwable { 

    // handling of query methods 
    // else 

    invocation.proceed(); 
    // ^^ works if not redeclared but not if 
    } 
} 

Donc ce que je voudrais faire au lieu de invocation.proceed() est la méthode qui détecte l'origine a déclaré celui qui est invoqué et invoquer que sur la cible manuellement.

+0

Je n'ai pas de réponse, mais je pense que MyExtendedInterface.class.getMethod ("foo", Bar.class) devrait être ok, avec un marqueur synthétique ou un pont. Est-ce que cela vous aide? – Istao

+0

Je ne comprends pas vraiment comment cela pourrait aider. Je parcoure les méthodes déclarées de 'MyExtendedInterface'. Le problème est que je ne peux pas les mettre en correspondance avec ceux déclarés dans MyImplementation. –

+0

Qu'est-ce que vous utilisez pour les proxies? javassiste? commons-proxy? – Bozho

Répondre

0

D'accord, voici la solution que j'ai trouvée: Comme je connais la classe de base et la structure générique (ce que T signifie dans ce cas) ainsi comme MyExtendedInterface types MyInterface à Bar je peux analyser la mise en œuvre de base pour les matches possibles comme suit (pseudo-code):

for all methods { 

    skip those with non matching name and parameters length; 

    for all generic parametertypes { 

    if typename = T then concrete type has to be Bar 
    ... 
    } 
} 

je le fais qui semble fonctionner pas besoin d'une solution générique dans ce cas.

0

Tout le scénario semble étrange. Vous ne pouvez pas appliquer AOP déclaré sur MyExtendedInterface à MyImplementation, car il ne l'implémente pas. Deuxièmement, je ne comprends pas pourquoi cela importe quelle interface définit une méthode, puisque c'est l'implémentation sur laquelle la méthode est invoquée. En outre, vous pouvez obtenir toutes les méthodes déclarées par une classe/interface donnée par getDeclaredMethods().Ensuite, vous pouvez itérer sur eux et trouver quelque chose qui correspond à vos critères (nom)

+0

Je peux. Je crée le proxy par programme et ajoute un intercepteur simple qui intercepte * chaque * appel de méthode. Dans cet intercepteur, je décide de l'endroit où acheminer l'appel de la méthode. 'getDeclaredMethods()' est une option mais je dois m'assurer que la méthode redéclarée remplace réellement celle de 'MyInterface. On pourrait aussi déclarer un 'foo (Foobar param)' qui ne remplacerait pas la méthode actuelle. Il semble donc qu'il n'y a aucun moyen de savoir si une méthode remplace une autre méthode esp. avec des génériques impliqués. –

+0

pourriez-vous fournir le code de l'intercepteur. Je ne comprends pas très bien ton scénario. – Bozho

+0

Ajout d'un code de création de proxy et d'un intercepteur à la question d'origine. –

Questions connexes