6
votes

Java - Enregistrez toutes les classes annotées avec @Myannotation

J'ai une annotation @myannotation code> et je peux annoter tout type (classe) avec elle. Ensuite, j'ai une classe appelée AnnotateClassregister Code> et j'aimerais qu'il enregistre toutes les classes annotées avec @myannotation code> afin que je puisse y accéder plus tard. Et j'aimerais enregistrer ces classes automatiquement lors de la création du annotéclassregister code> si possible, et surtout avant que les classes annotées ne soient instanciées.

J'ai de l'aspect et de la Guice à ma disposition. La seule solution que j'ai proposée jusqu'à présent consiste à utiliser Guice pour injecter une instance Singleton de l'annotation code> à un aspect, qui recherche toutes les classes annotées avec @myannotation code> et il Ajoute le code nécessaire pour enregistrer une telle classe dans son constructeur. L'inconvénient de cette solution est que j'ai besoin d'instancier chaque classe annotée pour que le code ajouté par AOP soit réellement exécuté, je ne peux donc pas utiliser l'instanciation paresseuse de ces classes. P>

Exemple de pseudo-code simplifié de Ma solution: P>

// This is the class where annotated types are registered
public class AnnotatedClassRegister {
    public void registerClass(Class<?> clz) {
        ...
    }
}

// This is the aspect which adds registration code to constructors of annotated
// classes
public aspect AutomaticRegistrationAspect {

    @Inject
    AnnotatedClassRegister register;

    pointcutWhichPicksConstructorsOfAnnotatedClasses(Object annotatedType) : 
            execution(/* Pointcut definition */) && args(this)

    after(Object annotatedType) :
            pointcutWhichPicksConstructorsOfAnnotatedClasses(annotatedType) {

        // registering the class of object whose constructor was picked 
        // by the pointcut
        register.registerClass(annotatedType.getClass())
    }
}


4 commentaires

A-t-il besoin d'être exécuté ou pouvez-vous faire la liste à la compilation?


Il doit être à l'exécution car c'est une fonctionnalité de cadre. Les utilisateurs du cadre utiliseront l'annotation pour annoter leurs classes et le cadre doit faire tout le travail sale pour les enregistrer lorsque la demande est lancée.


D'accord, mais l'Assemblée pourrait encore être faite au moment de la compilation, tant que le cadre sait comment le trouver au moment de l'exécution, non?


Eh bien, les implémentations JPA le font à l'exécution des classes annotées avec @enttity etc. Utilisent-ils un moyen standard commun de récupérer toutes les classes annotées ou vérifient-ils tout le chargeur de classe pour eux?


5 Réponses :


4
votes

Ce n'est pas simple que beaucoup est sûr, mais je le ferais de manière pure Java:

  • Obtenez l'emplacement de votre application de votre application à partir de la classe de classe
  • Créez un objet JARFILE avec cet endroit, itérale sur les entrées
  • pour chaque entrée qui se termine par .Class faire un class.forname () pour obtenir l'objet de la classe
  • Lisez l'annotation par réflexion. Si c'est présent, stockez la classe dans une liste ou définir

    Les aspects ne vous aideront pas là-bas, car les aspects ne fonctionnent que sur le code qui est réellement exécuté.

    mais Annotation Le traitement peut être une option, créer un processeur qui enregistre toutes les classes annotées et crée une classe qui fournit une liste de ces classes


5 commentaires

Merci pour votre réponse! Mais que se passe-t-il si je n'ai pas de fichier jar? C'est une application Web en cours d'exécution sur Tomcat dans le répertoire EXploDed WAR . Je vais regarder dans le traitement de l'annotation pendant ce temps ..


@Equi Dans ce cas, utilisez la réponse de Peter, qui est une légère variation de la mine qui fonctionnera également avec des fichiers de guerre éclatés (ou utilisez le traitement de l'annotation)


Le traitement de l'annotation semble que cela ferait ce que je veux, mais cela a besoin de moi pour spécifier quelles classes à traiter et que je ne sais pas avant l'exécution. J'ai trouvé cela Nice article qui explique comment le traitement peut être le traitement Exécuter de manière programmable à partir du code Java, mais comment puis-je traiter toutes les classes de la classe de classe de l'application Web?


@Equi Mais cela a besoin de moi pour spécifier les classes à traiter Nope. La seule chose que vous devez savoir est quelle annotation à rechercher. Vous ne pouvez pas exécuter le traitement de l'annotation à partir du conteneur Web. APT fonctionne sur des sources, non compilées de cours, cela fait partie du processus de construction.


+1 pour élargir mes horizons parce que je ne savais pas qu'une telle chose que le traitement de l'annotation existait même. Je donnerais un autre +1 pour vos explications, mais je ne peux pas :) Quoi qu'il en soit, je l'ai eu bien fonctionnant grâce au code Snippet @Peter. Merci à vous deux!



7
votes

Il est possible:

  1. Obtenez tous les chemins dans une classe de classe. Parse system.geproperties (). GetProperty ("java.class.path", null) pour obtenir tous les chemins.

  2. Utilisez classloader.getresources (chemin) Pour obtenir toutes les ressources et vérifier les cours: http://snippets.dzone.com/posts/show/4831


2 commentaires

L'extrait de code que vous avez posté m'a aidé et il semble que ce que je cherche! Merci!


Lien brisé (mai / 2017)



1
votes

Eh bien, si votre annotéclassregister.registerclass () ne doit pas être appelé immédiatement à annotéclassregister temps de création, mais cela pourrait attendre jusqu'à ce qu'une classe soit d'abord instanciée, Ensuite, je envisagerais d'utiliser une Guice Typelistener , enregistrée avec un correspondeur qui vérifie si une classe est annotée avec @myannotation .

De cette façon, vous n'avez pas besoin de rechercher toutes ces classes, elles seront enregistrées juste avant d'être utilisées. Notez que cela ne fonctionnera que pour les cours qui sont instanciés par Guice.


0 commentaires

0
votes

J'utiliserais la staticialisation () code> PointeCut dans AspectJ et amendez des cours à votre registre car ils sont chargés, comme:

after() : staticinitialization(@MyAnnotation *) {
    register.registerClass(thisJoinPointStaticPart.getSignature().getDeclaringType());
}


0 commentaires

0
votes

Vous pouvez utiliser le ClassGraph Emballez comme:

Java: xxx

scala: xxx


0 commentaires