DEV Community

K Adithyan
K Adithyan

Posted on

Custom Annotation Scanning with Spring Boot

In Java programming language, annotation offers a super way for supplying meta information about our code. These meta information can be used by frameworks to decide the functionality of that particular feature. When you design a module or a feature, you can define your own annotations and your feature can use it to achieve the functionalities similar to the existing frameworks

The information in the annotaion is made available to the runtime of the code in 2 ways.

  1. Using annotation processor. Annotation Processors are called by java compiler to process the information given at the AnnotatedElements to generate new Java source files or other meta-data
  2. Scanning the annotations during the JVM startup and using Java reflection, the AnnotatedElements can be identified and we can create meta models accordingly.

This article deals with the 2nd way of scanning the annotated classes from the classpath or methods or variables in the runtime and using it for our feature.

There are libraries like classgraph that can be used in java applications that do not use spring framework. If your application do not use spring framework or spring boot, you can refer to the classgraph library documentation and proceed.

If your application uses spring framework, then you can use the below snippet and get the list of classes that have been annotated with a particular annotation

If your custom annotation is @MyCustomAnnotation, you can find all the classes which are annotated with annotation @MyCustomAnnotationusing the below function call

findAnnotatedClasses(MyCustomAnnotation.class, "com.abc.def.xyz")

The packages list is given as varargs as it would enable neat code in the calling places.

The implementation of findAnnotatedClasses() method is given below. The class ClassPathScanningCandidateComponentProvider of spring framework does the magic of scanning the entire classpath and returns us the Bean classes which have the annotation @MyCustomAnnotation.

For spring framework to scan your class that has your custom annotation @MyCustomAnnotation,

your class must be annotated with @Component or the other spring annotations that make your class a managed component of Spring.

public Set<String> findAnnotatedClasses(Class<? extends Annotation> annotationType, String... packagesToBeScanned)
{
    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
    provider.addIncludeFilter(new 
    AnnotationTypeFilter(annotationType));

    Set<String> ret = new HashSet<>();

    for (String pkg : packagesToBeScanned)
    {
         Set<BeanDefinition> beanDefs = provider.findCandidateComponents(pkg);
         beanDefs.stream()
             .map(BeanDefinition::getBeanClassName)
             .forEach(ret::add);
    }

    return ret;
}
Enter fullscreen mode Exit fullscreen mode

Spring Application's main class below shows how to call this method.

@SpringBootApplication
public class SpringApp implements CommandLineRunner
{
    @Autowired
    private ClassScanner classScanner;

    public static void main(String[] args)
    {
        SpringApplication.run(SpringApp.class, args);
    }

    @Override
    public void run(String... args) throws Exception
    {
        Set<String> annotatedClasses = classScanner.findAnnotatedClasses(MyCustomAnnotation.class, "xyz.reachadi");

        for (String c : annotatedClasses)
            System.out.println("Annotated Class : " + c);
    }
}
Enter fullscreen mode Exit fullscreen mode

The approach is very simple..... right?

So, what next? Enhance your codes' readability by defining custom annotations and using them on your codes.

The full working example of this blog is available in my github repository.

Please refer to readme.md for instructions on running the tutorial.

Top comments (3)

Collapse
 
siy profile image
Sergiy Yevtushenko

Run-time reflection and class path scanning are great ways to make Java apps slow, memory hungry and taking ages to start.

Collapse
 
adithyank profile image
K Adithyan

True. But, based on the application and the scope of scanning, developers can make a tradeoff to utilize this annotation based design....!

Collapse
 
siy profile image
Sergiy Yevtushenko

I think that run-time reflection should be avoided as much as possible. Just take a look at Micronaut - same convenience and flexibility and no drawbacks of run-time reflection.