Outils pour trouver des classes annotées en Java

Cet article fournit un bref aperçu de trois outils pour rechercher des classes annotées dans un projet java.


image


Dresser des chats
@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation {} @MyAnnotation public class Bar {} @MyAnnotation public class Foo {} 

Printemps


Au printemps, ClassPathScanningCandidateComponentProvider sert à cet effet.


Fonctionnalité: rampe dans ClassPath, à la recherche de classes qui satisfont aux conditions données

Fonctionnalités supplémentaires

possède de nombreux autres filtres (pour le type, pour les méthodes, etc.)


Exemple


 @Benchmark public void spring() { ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnotation.class)); List<String> collect = scanner .findCandidateComponents("edu.pqdn.scanner") .stream() .map(BeanDefinition::getBeanClassName) .filter(Objects::nonNull) .collect(Collectors.toList()); assertEquals(collect.size(), 2); assertTrue(collect.contains("edu.pqdn.scanner.test.Bar")); assertTrue(collect.contains("edu.pqdn.scanner.test.Foo")); } 

Réflexions


Fonctionnalité: rampe dans ClassPath, à la recherche de classes qui satisfont aux conditions données

Fonctionnalités supplémentaires
  • obtenir tous les sous-types d'un certain type
  • obtenir tous les types / membres annotés avec une certaine annotation
  • obtenir toutes les ressources correspondant à une expression régulière
  • obtenir toutes les méthodes avec une signature spécifique, y compris les paramètres, les annotations de paramètres et le type de retour

dépendance
 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version> </dependency> 

Exemple


 @Benchmark public void reflection() { Reflections reflections = new Reflections("edu.pqdn.scanner"); Set<Class<?>> set = reflections.getTypesAnnotatedWith(MyAnnotation.class); List<String> collect = set.stream() .map(Class::getCanonicalName) .collect(Collectors.toList()); assertEquals(collect.size(), 2); assertTrue(collect.contains("edu.pqdn.scanner.test.Bar")); assertTrue(collect.contains("edu.pqdn.scanner.test.Foo")); } 

classindex


Fonctionnalité: N'entre PAS dans ClassPath, à la place, les classes sont indexées au moment de la compilation

dépendance
 <dependency> <groupId>org.atteo.classindex</groupId> <artifactId>classindex</artifactId> <version>3.4</version> </dependency> 

Dresser des chats
 @IndexMyAnnotated public @interface IndexerAnnotation {} @IndexerMyAnnotation public class Bar {} @IndexerMyAnnotation public class Foo {} 

Exemple


 @Benchmark public void indexer() { Iterable<Class<?>> iterable = ClassIndex.getAnnotated(IndexerMyAnnotation.class); List<String> list = StreamSupport.stream(iterable.spliterator(), false) .map(aClass -> aClass.getCanonicalName()) .collect(Collectors.toList()); assertEquals(list.size(), 2); assertTrue(list.contains("edu.pqdn.scanner.classindexer.test.Bar")); assertTrue(list.contains("edu.pqdn.scanner.classindexer.test.Foo")); } 

Jmh


 Benchmark Mode Cnt Score Error Units ScannerBenchmark.indexer avgt 50 0,100 ? 0,001 ms/op ScannerBenchmark.reflection avgt 50 5,157 ? 0,047 ms/op ScannerBenchmark.spring avgt 50 4,706 ? 0,294 ms/op 

Conclusion


Comme vous pouvez le voir, l'indexeur est l'outil le plus productif, cependant, les annotations utilisées pour la recherche doivent avoir le stéréotype @IndexAnnotated.


Les deux autres outils fonctionnent beaucoup plus lentement, mais pour leur travail, aucun chamanisme avec le code n'est nécessaire. L'inconvénient est complètement nivelé si la recherche n'est nécessaire qu'au début de l'application

Source: https://habr.com/ru/post/fr424511/


All Articles