Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scanning Java annotations at runtime [closed]

People also ask

What is @interface annotation in Java?

@interface is used to create your own (custom) Java annotations. Annotations are defined in their own file, just like a Java class or interface. Here is custom Java annotation example: @interface MyAnnotation { String value(); String name(); int age(); String[] newNames(); }

How are annotations executed in Java?

Annotations don't execute; they're notes or markers that are read by various tools. Some are read by your compiler, like @Override ; others are embedded in the class files and read by tools like Hibernate at runtime.

How does spring find annotated classes?

Spring has something called a AnnotatedTypeScanner class. This class has the code for actual scanning of the classpath resources. It does this by using the class metadata available at runtime.


Use org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

API

A component provider that scans the classpath from a base package. It then applies exclude and include filters to the resulting classes to find candidates.

ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>);

scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));

for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
    System.out.println(bd.getBeanClassName());

And another solution is Google reflections.

Quick review:

  • Spring solution is the way to go if you're using Spring. Otherwise it's a big dependency.
  • Using ASM directly is a bit cumbersome.
  • Using Java Assist directly is clunky too.
  • Annovention is super lightweight and convenient. No maven integration yet.
  • Google reflections pulls in Google collections. Indexes everything and then is super fast.

You can find classes with any given annotation with ClassGraph, as well as searching for other criteria of interest, e.g. classes that implement a given interface. (Disclaimer, I am the author of ClassGraph.) ClassGraph can build an abstract representation of the entire class graph (all classes, annotations, methods, method parameters, and fields) in memory, for all classes on the classpath, or for classes in whitelisted packages, and you can query that class graph however you want. ClassGraph supports more classpath specification mechanisms and classloaders than any other scanner, and also works seamlessly with the new JPMS module system, so if you base your code on ClassGraph, your code will be maximally portable. See the API here.


If you want a really light weight (no dependencies, simple API, 15 kb jar file) and very fast solution, take a look at annotation-detector found at https://github.com/rmuller/infomas-asl

Disclaimer: I am the author.


You can use Java Pluggable Annotation Processing API to write annotation processor which will be executed during the compilation process and will collect all annotated classes and build the index file for runtime use.

This is the fastest way possible to do annotated class discovery because you don't need to scan your classpath at runtime, which is usually very slow operation. Also this approach works with any classloader and not only with URLClassLoaders usually supported by runtime scanners.

The above mechanism is already implemented in ClassIndex library.

To use it annotate your custom annotation with @IndexAnnotated meta-annotation. This will create at compile time an index file: META-INF/annotations/com/test/YourCustomAnnotation listing all annotated classes. You can acccess the index at runtime by executing:

ClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)

There's a wonderful comment by zapp that sinks in all those answers:

new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)