Using Bytebuddy assume the following:
class Service {
protected Handler handler;
...
}
interface Handler {
public void handle();
}
class ConcreteHandler implements Handler {
public void handle() {
...
}
public void handle2() {
...
}
}
Generally we call the handle() method of Handler, but in some cases we need to call handle2() of ConcreteHandler's class which is it in runtime. Now the question: is that possible using Bytebuddy? Probably yes, but how?
i tried that:
if (condition) {
MethodCall methodCall = (MethodCall)
MethodCall.invoke(methodHandle2).onField("handler")
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC);
}
... but it fails with an IllegalStateException: Cannot invoke public void com.framework.ConcreteHandler.handle2(...) on protected com.framework.Handler com.framework.Service.handler
Any ideas?
This seems to be a bug in Byte Buddy. I hopefully fixed the issue in this commit which should resolve the issue in Byte Buddy 1.10.14. You can try the snapshot in the meantime.
If your field variable is a Handler
, you cannot call handle2()
, since Handler's don't know about the handle2()
method.
In order to call the handle2()
method (for a valid class), you'd need to cast the handler
to a ConcreteHandler
- a process known as "downcasting" as you're casting the instance to an object lower down in the object hierarchy. This only works when the handler
instance is actually a ConcreteHandler
rather than some other derivation of the Handler
.
example:
if (handler instanceof ConcreteHandler) {
ConcreteHandler concreteHandler = (ConcreteHandler) handler;
concreteHandler.handle2();
}
EDIT: The one-off redirect I got working. I'm not entirely certain how you'd get it working as a permanent redirect from the docs but it would seem like redefine would work if you wanted to permanently redirect the method. There was also a change to the source necessary to make the classes ConcreteHandler, Handler, etc, public.
new ByteBuddy()
.subclass(ConcreteHandler.class)
.method(named("handle")).intercept(MethodDelegation.to(ConcreteHandler.class))
.make()
.load(getClass().getClassLoader())
.getLoaded()
.newInstance()
.handle2();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.