Java - Using Reflections To Scan Classes From All Packages

1.5k views Asked by At

I am developing an application that is supposed to scan all classes and interfaces in a given classpath and match an implementing class for DI creation.

I have an annotation:

@Target(TYPE)
@Retention(RUNTIME)
public @interface RequiresBinding {

}

and an interface:

@RequiresBinding
public interface LowerToUpperSocketCreator {

  void createSocket(int lowerToUpperPort);

  void setIp(InetAddress ip);

  DatagramSocket getSocket();
}

The problem is that I can't tell in advance which packages use these annotations, so I need to scan all available classes that has this annotation.
I have tried the following code:

Reflections reflections1 = new Reflections("", new TypeAnnotationsScanner(), new SubTypesScanner());
    Set<Class<?>> bindingProvidingClasses = reflections1.getTypesAnnotatedWith(ProvidesBinding.class);

The symptom is that I am unable to find classes that haven't been loaded yet: At this example, classes that are in a different JAR than the application's JAR (the application has a dependency on that JAR), won't be scanned.
If I change the new Reflections("") command into a new Reflections("com"), meaning not a completely dummy Reflections object, but an object that has all packages starting with com, indeed I was able to scan all classes.
Is there a way to scan all classes in the classpath without having any information on the relevant packages or the available JARs?

1

There are 1 answers

0
Jean Alexandre On

You can try listing all the possible packages and adding them to the Reflection object like this:

Collection<URL> allPackagePrefixes = Arrays.stream(Package.getPackages()).map(p -> p.getName())
        .map(s -> s.split("\\.")[0]).distinct().map(s -> ClasspathHelper.forPackage(s)).reduce((c1, c2) -> {
            Collection<URL> c3 = new HashSet<>();
            c3.addAll(c1);
            c3.addAll(c2);
            return c3;
        }).get();
ConfigurationBuilder config = new ConfigurationBuilder().addUrls(allPackagePrefixes)
        .addScanners(Scanners.SubTypes);
Reflections reflections = new Reflections(config);

It worked for me, but I'm not sure how expensive it is ressource-wise.