Reputation: 1459
I know there are incredible set of tools for loading plugin classes in java, but today an idea came to my mind.
What if I have a bunch of annotated and un-annotated classes in package "org.home.junk" (annotated with annotation "@AnnotatedClass") and those classes have annotated methods with say annotation "@AnnotatedMethod".
First question: can I at run-time get an array/collection of all the classes in that specific package, so that I could check which one's are annotated and create an instance of them. (I am aware however how to check if Some.class has annotations courtesy of this guide: http://isagoksu.com/2009/development/java/creating-custom-annotations-and-making-use-of-them/)
Second question: - If I can do what I'd like in first question - what would be the most political way to do this?
I believe it is possible, as I understand JUnit loads test-case classes in some similar manner.
Also it would be cool if this could be done with minimal third party libraries and such, again - if it's possible :)
Upvotes: 26
Views: 32543
Reputation: 1202
It can be done with techniques that check the filesystem because it is more a classloader issue than a reflection one. Check this: Can you find all classes in a package using reflection?.
If you can check all the class files that exists in a directory, you can easily get the corresponding class using this method
Class<?> klass = Class.forName(className)
To know if a class is annotated or not is a reflection issue. Getting the annotations used in a class is done this way:
Annotation[] annotations = klass.getAnnotations();
Be sure to define your custom annotation with a retention policy type visible at run time.
@Retention(RetentionPolicy.RUNTIME)
This article is a good resource for more info on that: http://tutorials.jenkov.com/java-reflection/annotations.html.
Upvotes: 2
Reputation: 8261
First answer: Take a look at this project.
Reflections reflections = new Reflections("org.home.junk");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(javax.persistence.Entity.class);
It returns all the classes from org.home.junk
annotated with javax.persistence.Entity
annotation.
Second Answer: To create new instance of above classes you can do this
for (Class<?> clazz : annotated) {
final Object newInstance = clazz.newInstance();
}
Hope this answers everything.
Upvotes: 31
Reputation: 19185
It all depends on what kind of requirement you have for annotation.
Like e.g. @EJB
: This annotation is designed so that container will identify and do EJB Specific work which requires scanning through files and then finding such classes.
However if your requirement is only to enable specific functionality based on annotation then you can do it using java reflection only
e.g. @NotNull
: This annotation is designed in JSR 303 to verify that Annotated element is not null. This functionality can be easily implemented at run time using reflection API
Upvotes: 1
Reputation: 8206
If you have Spring(3rd party, sorry :-)), use the org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
A code usage example can be found in this SO question
Upvotes: 2