Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I am putting together a very simple ByteBuddy delegate/proxy class.
The intention is (again, very simple) to proxy a class such that any of its non-
final
, non-
private
, non-
static
methods and so forth get routed to equivalent methods on its
proxiedInstance
field as returned by its
getProxiedInstance
method. (There should be exceptions made for the usual suspects:
equals
,
hashCode
,
wait
and
notify
and so on.)
I've set up my proxy class using the subclass strategy. I've also defined two methods,
getProxiedInstance
and
setProxiedInstance
, along with a
private
field named
proxiedInstance
of the proper type. I've done this using the
FieldAccessor.ofBeanProperty()
strategy. I've omitted that here for brevity and clarity. The class does in fact contain this field and these two methods.
Then I've defined the method interception like this, statically importing the relevant
ElementMatchers
methods:
builder
.method(not(isFinal()).and(not(isStatic())).and(not(isPrivate()))
.and((isPublic().and(named("toString")).and(takesArguments(0)).and(returns(String.class)))
.or((not(isDeclaredBy(Object.class)).and(not(named("getProxiedInstance"))).and(not(named("setProxiedInstance"))))))
.intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"));
In English: not final
, not static
, not private
, and either the public String toString()
method inherited from Object
(or overridden), or any other method not declared by Object.class
and not named getProxiedInstance
or setProxiedInstance
.
Suppose I have a class like this:
public class Frob {
public String sayHello() {
return "Hello!";
When I create a proxy class for it, instantiate it, and then call toString()
on the proxy, I get Hello!
.
This suggests to me somehow that the recipe I've quoted above is somehow routing toString()
to sayHello()
.
From reading the MethodDelegation
javadocs, it seems that maybe sayHello
on the target/delegate object is picked for delegation because it is more specific than the method invoked on the proxy (toString
). I guess name matching is lower priority than that.
I think this use case I have is relatively simple. How do I best accomplish it?
The best I could do, which works, but seems perhaps a little clunky or verbose, was this:
builder = builder
.method(not(isDeclaredBy(Object.class))
.and(not(isFinal()))
.and(not(isStatic()))
.and(not(isPrivate()))
.and(not(named("getProxiedInstance")))
.and(not(named("setProxiedInstance"))))
.intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"))
.method(is(toStringMethod))
.intercept(invoke(toStringMethod).onMethodCall(invoke(named("getProxiedInstance"))));
(toStringMethod
is the Method
resulting from Object.class.getMethod("toString")
.)
I think using MethodCall
is a better approach to this. MethodDelegation
is meant for "catch all proxies" where you inject corresponding dispatchers into what is often a single delegate method, maybe two. Method call is also much more performance since it does not need to do the analysis but just reroutes to a method of a compatible type.
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.