Reflexion is an answer, but you need to get all the classes from the classpath, and examinate it to find the implementation of your interface.
You can use this reflection library and get all the implementations like this (if your interface name is MyInterface):
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
for (Class<T extends MyInterface> c : classes) {
check if c is the rigth implementation!.
}
If you don't want to use a external library, you can use the Java Reflection API, and scan all packages, somethis like (see this answers to use instrumentation):
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> c: inst.getAllLoadedClasses()) {
if (MyInterface.class.isAssignableFrom(c)) {
check if c is the rigth implementation!.
}
}
The first option allow you to save the Reflections
object as a xml, so the component scan is saved and it's done only one time.
To check if the clazz
have a Qualifier
you can use:
if (c.isAnnotationPresent(Qualifier.class)) {
bingo!.
}
or is a property of the annotation:
if (c.isAnnotationPresent(Qualifier.class)) {
Qualifier q = c.getAnnotation(Qualifier.class);
if (q.theRight()) {
bingo!
}
}
I recommend you to see if the FactoryProblem
is applycable to your problem, choose always Factory
instead of Reflection
.
An example "proxy":
public class MyProxy implements GenericI {
Map<Category, GenericI> generics;
public MyProxy() {
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
generics = new HashMap<Category, GenericI>();
for (Class<T extends MyInterface> c : classes) {
map.put(c.getAnnotation(MyAnnotation.class).value(), c.newInstance());
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
This is extremely heavy and overcomplicated, if you use this, please add extensive test, and make MyProxy
a Singleton.
If you use a IOC framework:
@Component
public class MyProxy implements GenericI {
@Autoriwed // If spring
List<GenericI> generics;
@Inject @Any // If CDI
private Instance<GenericI> services;
Map<Category, GenericI> generics;
@PostConstruct
void makeMap() {
generics = new HashMap<>();
for (GenericI component : generics) {
generics.put(
component.getClass().getAnnotation(MyAnnotation.class).value(),
component);
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
I assume you don't know al possible subclasses.