| home / internet / reflection / 1 | [previous] [next] |
|
|
Proxy allows programmers to accomplish the delegation task by providing the InvocationHandler interface. Instances of InvocationHandler, also referred to as invocation handlers, are objects that handle each method call for a proxy instance. Invocation handlers are also responsible for holding any references to targets of the proxy instance. Listing 4.2 shows the InvocationHandler interface.
Listing 4.2 The InvocationHandler interface
public interface InvocationHandler {
public Object invoke( Object proxy, Method method, Object[] args )
throws Throwable;
}
A proxy instance forwards method calls to its invocation handler by calling
invoke. The original arguments for the method call are passed to
invoke as an object array. In addition, the proxy instance provides
a reference to itself and to a Method object representing the invoked
method.
Notice that the parameters passed to invoke are exactly the objects
needed to forward a method call to another object reflectively. If target
refers to the object being proxied, the lines
public Object invoke( Object proxy, Method method, Object[] args)
throws Throwable
{
return method.invoke(target, args);
}
implement an invoke method that passes every call transparently. More complex invoke methods may perform pre- and post-processing on the arguments. Note that invocation handlers may also forward to many targets or none at all.
Figure 4.1 depicts an abstraction of forwarding a method through a proxy. Figure 4.2 depicts that actual sequence of calls when the invocation handler is implemented as shown previously. For clarity, UML is often used to present the minimal relevant detail to convey understanding. With this idea in mind, our subsequent diagrams for proxy present the abstraction rather than the implementation detail.
A proxy instance is an object, and so it responds to the methods declared by
java.lang.Object. This raises the issue of whether or not these
methods should be handled by invoke. The issue is resolved as follows:
hashCode, equals, and toString are dispatched
to the invoke method in the same manner as any other proxied method.
Cloneable, then the invocation
handler does intercede on the invocations to clone. However, unless
the proxied interface makes clone public, it remains a protected
method.
finalize,
then invocation handlers do intercede on calls to finalize.
java.lang.Object. Consequently, these methods behave as expected
for any instance of java.lang.Object. In other words, a call to
wait on a proxy instance waits on the proxy instance's lock, rather
than being forwarded to an invocation handler.
The information in the last bullet is welcome because it means that an invocation handler cannot make a proxy instance lie about its class or interfere with multi- threaded locking. Now that you understand the basics of Proxy, let’s return to George’s tracing problem.
George solves his tracing problem using Proxy. From his exploration of Proxy,
George readily understands that his solution must have an invocation handler in
which the invoke method forwards all method calls to the target. This forwarding
is readily accomplished with the invoke method of Method. The next design decision
involves the creation of the proxy and the invocation handler. George
decides that all of his creation code can be located in the class written for the
invocation handler. This is accomplished with a static method, createProxy. This
static method is passed the target, which is examined introspectively to create an
appropriate proxy and invocation handler. Listing 4.3 shows the invocation handler
that George created. With this invocation handler, George can add tracing of
any interface to an individual object. Let’s examine the solution in detail.
Listing 4.3 An invocation handler for a proxy that traces calls
| home / internet / reflection / 1 | [previous] [next] |
Created: March 27, 2003
Revised: November 12, 2004
URL: http://webreference.com/internet/reflection/1