Tools zum Suchen von kommentierten Klassen in Java

Dieser Artikel bietet einen kurzen Überblick über drei Tools zum Auffinden kommentierter Klassen in einem Java-Projekt.


Bild


Katzen trainieren
@Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation {} @MyAnnotation public class Bar {} @MyAnnotation public class Foo {} 

Frühling


Im Frühjahr dient ClassPathScanningCandidateComponentProvider zu diesem Zweck.


Feature: Crawlt in ClassPath und sucht nach Klassen, die die angegebenen Bedingungen erfüllen

Zusätzliche Funktionen

hat viele andere Filter (für Typ, für Methoden usw.)


Beispiel


 @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")); } 

Reflexionen


Feature: Crawlt in ClassPath und sucht nach Klassen, die die angegebenen Bedingungen erfüllen

Zusätzliche Funktionen
  • Holen Sie sich alle Untertypen eines Typs
  • Alle Typen / Mitglieder mit Anmerkungen versehen
  • Holen Sie sich alle Ressourcen, die einem regulären Ausdruck entsprechen
  • Rufen Sie alle Methoden mit einer bestimmten Signatur ab, einschließlich Parameter, Parameteranmerkungen und Rückgabetyp

Abhängigkeit
 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version> </dependency> 

Beispiel


 @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")); } 

Klassenindex


Feature: Geht NICHT in ClassPath, stattdessen werden Klassen zur Kompilierungszeit indiziert

Abhängigkeit
 <dependency> <groupId>org.atteo.classindex</groupId> <artifactId>classindex</artifactId> <version>3.4</version> </dependency> 

Katzen trainieren
 @IndexMyAnnotated public @interface IndexerAnnotation {} @IndexerMyAnnotation public class Bar {} @IndexerMyAnnotation public class Foo {} 

Beispiel


 @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 

Fazit


Wie Sie sehen, ist der Indexer das produktivste Werkzeug. Die für die Suche verwendeten Anmerkungen sollten jedoch das Stereotyp @IndexAnnotated aufweisen.


Die anderen beiden Tools arbeiten viel langsamer, aber für ihre Arbeit ist kein Schamanismus mit dem Code erforderlich. Der Nachteil wird vollständig ausgeglichen, wenn die Suche erst zu Beginn der Anwendung erforderlich ist

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


All Articles