5

I know we can get all methods with a particular annotation inside a class. But I want all methods inside a package with that annotation. My use case : I want to annotate and identify few set of methods and ask my user to choose one of them add in a flow to execute.

@Retention(RetentionPolicy.RUNTIME)
@Target({ METHOD })
public @interface Step {
    String Type();// default "Trigger";
    String SubType();
    String [] tags();
}

public interface APITrigger {

    @Step(Type = "TRIGGER", SubType = "GET_CLASS_INSTANCE", tags = { "trigger", "build instance", "class object" })
    public Object getClassInstance(@NonNull final String packageNclassName)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, NoSuchFieldException;

    @Step(Type = "TRIGGER", SubType = "INVOKE_API_N_RETURN", tags = { "trigger", "hit api", "trigger api and return" })
    public Map<Class<?>, Object> invokeOveloadedAPINReturn(@NonNull final Object classInstance,
            @NonNull final String methodName);
}
public interface Comparator {

    @Step(Type = "COMPARATOR", SubType = "GENERIC_COMPARATOR", tags = { "compare", "expected", "observed", "any type", "generic comparator" })
    public <T> ComparisonResult Compare(T Expected, T Observed);

}

I want list of methods [getclassinstance, invokeOveloadedAPINReturn, Compare] as those three are annotated with Step. Can we do this with reflection? Also, can we restrict our search with variables inside annotation as well?

Vivek Krishna
  • 89
  • 4
  • 12
  • 2
    you already know how to get all methods with a particular annotation inside a class. Find out how to get all classes in a package then loop. – jhamon Aug 09 '18 at 09:34
  • @jhamon it might be bad idea to load all classes from application - especially if many of them are not used if some features are not enabled or are system depended and can throw error on load. But still +1 as this is good step that OP should try to find the answer before asking. – GotoFinal Aug 09 '18 at 10:13

1 Answers1

7

Best way is to use Reflections (this is name of this library) it allows for very simple scans of classpath to look for classes or methods with given annotations.

Set<Method> methodsAnnotatedWith = new Reflections("my.package", new MethodAnnotationsScanner()).getMethodsAnnotatedWith(SomeAnnotation.class);

If you want to write own one for some reason, then you need to get classpath and urls from given class loaders to manually scan for class files in given location to load them and check if they have given annotations/methods. This library also does that without loading classes you don't need, as scan itself is not loading classes, only classes that matches your "query" are loaded. (and it is doing that by loading .class files to own data structures)

GotoFinal
  • 3,585
  • 2
  • 18
  • 33
  • Thank you so much for your solution sir, but can we restrict our search based on variables inside out annotation as well? Like Step annotation with Type = "TRIGGER" etc in this case. – Vivek Krishna Aug 09 '18 at 11:08
  • @VivekKrishna yes, there is also methods that require `getMethodsAnnotatedWith(Annotation annotation)` but you need annotation instance - but you can just create class that is implementing given annotation like any other interface and use it as this lookup pattern. There are also libraries that allows you to create annotation from map of values and class – GotoFinal Aug 09 '18 at 12:22
  • 1
    @VivekKrishna ah, but you can't filter only by one annotation parameter, so it would be better to just do it after that global scan – GotoFinal Aug 09 '18 at 12:38