Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Scanning the Java Classpath for Specific Annotation Types

Tools 2

Identifying all classes decoratde with a particular annotation requires traversing the runtime classpath and inspecting type metadata. The standard Java reflection API cannot enumerate classes on its own; it only inspects types that have already been loaded by the classloader. Consequently, an external classpath scanning utility is necessary.

Prerequisites

Add a dedicated scanning library to the project dependencies. The org.reflections library provides efficient metadata indexing:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.10.2</version>
</dependency>

Define the Marker

Create a runtime-retained annotation. The RetentionPolicy.RUNTIME directive is mandatory to preserve metadata during execution.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DataProcessor {
    String category() default "default";
}

Configuration and Scanning

Initialize the scanner with explicit package boundaries. Scanning the entire classpath introduces unnecessary latency and may trigger unwanted class loading.

import org.reflections.Reflections;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

import java.util.Set;

public class TypeLocator {

    private static final String BASE_PACKAGE = "com.system.core";

    public static Set<Class<?>> locateAnnotatedTypes() {
        ConfigurationBuilder indexConfig = new ConfigurationBuilder()
                .forUrls(ClasspathHelper.forPackage(BASE_PACKAGE))
                .setExpandSuperTypes(false);

        Reflections classpathIndex = new Reflections(indexConfig);
        
        return classpathIndex.getTypesAnnotatedWith(DataProcessor.class);
    }
}

Result Processing

The scanner returns a Set of Class objects. Apply filtering to exclude interfaces and abstract implementations before utilizing the types.

import java.util.ArrayList;
import java.util.List;

public class ComponentRegistry {
    
    public static List<Class<?>> buildActiveComponents() {
        List<Class<?>> validTargets = new ArrayList<>();
        
        for (Class<?> rawType : TypeLocator.locateAnnotatedTypes()) {
            if (rawType.isInterface() || java.lang.reflect.Modifier.isAbstract(rawType.getModifiers())) {
                continue;
            }
            validTargets.add(rawType);
        }
        
        return validTargets;
    }
    
    public static void main(String[] runtimeArgs) {
        for (Class<?> activeClass : buildActiveComponents()) {
            DataProcessor metadata = activeClass.getAnnotation(DataProcessor.class);
            System.out.printf("Resolved: %s | Category: %s%n", activeClass.getName(), metadata.category());
        }
    }
}

Optimization Guidelines

Classpath indexing is computationally expensive during application bootstrap. Restrict the configuration to narrow package scopes and store the resulting collection in an immutable cache if multiple lookups are expected. Avoid re-executing the scan within request-handling threads or frequently invoked loops.

Tags: Java

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.