Reputation: 13432
I intend to import a library(jar) using my custom ClassLoader and it turns out the requirement is there to set a listener on one of the classes, like,
Class<?> clazz = getInitializerClass();
Object initializer = clazz.newInstance();
// I would like the below listener to be set on this initializer reflectively
// setOnInitListener() is mathod to be called on initializer
setOnInitListener(new OnInitCompleteListener(){
@Override
public void onInit(){
}
}
The issue is that I don't have the listener available as a import and all I can get is a OnInitCompleteListener.class
dynamically by classloading on the fly.
How can I achieve the above?
Note: I am willing to go any limits to achieve the same but a simple approach would be appreciated.
Upvotes: 1
Views: 71
Reputation: 726589
Anonymous classes are compile-time artifacts. They even have names by which Java compiler can identify them, albeit inaccessible to programmers.
However, there is a work-around: since OnInitCompleteListener
is an interface, you can produce a dynamic proxy that implements your interface:
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("onInit")) {
... // Listener's code goes here
}
}
};
Class<T> onInitCompleteListenerClass = ... // You get this one dynamically
Object listener = Proxy.newProxyInstance(
classLoader,
new Class[] { onInitCompleteListenerClass },
handler);
// Use listener in the reflective call to a method taking OnInitCompleteListener
MyInvocationHandler
implements InvocationHandler
interface. Its invoke
method can detect that it's being called in place of onInit
, and perform the work as necessary.
Upvotes: 2
Reputation: 2702
Assuming your OnInitCompleteListener
class is available in the same classloader you're running the rest of this code in...
You can get ahold of the setOnInitListener
method with reflection against the class instance:
Method setter = clazz.getDeclaredMethod("setOnInitListener", OnInitCompleteListener.class);
setter.invoke(initializer, new OnInitCompleteListener() {
@Override
public void onInit() {
// implementation
}
});
Upvotes: 0