corejava11 (6.5 Agent)

6.5 Proxy

In the last section of this chapter, we will discuss the agency. Agents can create a new class that implements a given set of interfaces at runtime to use. Only we do not know at compile time when the need to implement an interface which only requires a proxy. For application programmers, this is not a common case, so if you are not interested in the Advanced Wizard, you can skip this section. However, for certain system programming applications, the flexibility provided by the agent can be very important.

6.5.1 When to use a proxy

Suppose you want to construct an object of a class that implements one or more interfaces, you may not know the exact nature of these interfaces at compile time. This is a difficult problem. To construct the actual classes, you can simply use the newInstancemethod or using reflection to find the constructor. But you can not instantiate an interface. You need to define a new class in the program is running.

To solve this problem, some program generated code, put it in a file, invoke the compiler, and then load the class files generated. Of course, this is very slow, but it also needs to be deployed together with the compiler program. Proxy mechanism is a better solution. Acting classes can create new classes at runtime. Such a proxy class that implements the interface that you specify. In particular, the proxy class has the following methods:

  • All methods specify the interfaces; and
  • ObjectAll methods defined in the class toString( , equalsetc.).

However, you can not define new code for these methods at runtime. Instead, you must provide a handler is called. Invocation handler is to achieve InvocationHandlerany kind of object interface. The interface is only one way:

Object invoke(Object proxy, Method method, Object[] args)

Whenever you call a method on the proxy object, call handler invokemethod is called, Methodthe parameters object and the original call as well. Then call handler must figure out how to handle the call.

6.5.2 Creating a proxy object

To create a proxy object, use the Proxyclass newProxyInstancemethods. The method takes three parameters:

  • Class loader. As part of the Java security model, a different class loader can be used for platform and application classes, downloaded from the Internet and so on. We will discuss loaders in Volume II Chapter 9. In this example, we specify the loading platform and applications like "system class loader."
  • ClassAn array of objects, each corresponding one of the interface to be achieved.
  • Call handler.

There are two issues. How do we define the handler? What can we do to generate a proxy object of it? Of course, the answer depends on the problem we want to solve the proxy mechanism. Agent can be used for various purposes, e.g.

  • The method calls are routed to a remote server
  • The user interface events associated with running programs in operation
  • Tracing method calls for debugging purposes

In our example program, we use a proxy and call handlers to trace method calls. We define a TraceHandlerwrapper class that stores objects of a package. Its invokeway to print only the name and parameters of the method to call, and then use the wrapped object as the implicit parameter called the method.

class TraceHandler implements InvocationHandler
{
    private Object target;
    public TraceHandler(Object t)
    {
        target = t;
    }
    public Object invoke(Object proxy, Method m, Object[] args)
        throws Throwable
    {
        // print method name and parameters
        . . .
        // invoke actual method
        return m.invoke(target, args);
    }
}

Here's how to construct a proxy object, every time you call one of its methods, the object will lead to stalking:

Object value = . . .;
// construct wrapper
var handler = new TraceHandler(value);
// construct proxy for one or more interfaces
var interfaces = new Class[] { Comparable.class};
Object proxy = Proxy.newProxyInstance(
    ClassLoader.getSystemClassLoader(),
    new Class[] { Comparable.class } , handler
);

Now, whenever proxythe upper method call from one of the interfaces, will print out the method name and parameters, then valuethe method call.

In the program shown in Listing 6.10, we use a proxy object tracking binary search. We use an integer of 1 - Agents fill an array of 1000. We then call the Arraysclass binarySearchmethod to search for random integer array. Finally, we print matching elements.

var elements = new Object[1000];
// fill elements with proxies for the integers 1 . . . 1000
for (int i = 0; i < elements.length; i++)
{
    Integer value = i + 1;
    elements[i] = Proxy.newProxyInstance(. . .); // proxy for value;
}
// construct a random integer
Integer key = new Random().nextInt(elements.length) + 1;
// search for the key
int result = Arrays.binarySearch(elements, key);
// print match if found
if (result >= 0) System.out.println(elements[result]);

IntegerClass implements the Comparableinterface. Proxy object belongs to class definitions at runtime. (It has a name, such as $Proxy0.) This class also implements the Comparableinterface. However, its compareTomethod call the proxy object handler invokemethod.

note

As you saw earlier in this chapter, Integer class actually implements Comparable<Integer>. However, at run time, all generic types will be cleared, and the proxy is using the original Comparableclass object of the class structure.

binarySearchCall the following method:

if (elements[i].compareTo(key) < 0) . . .

Because we fill the array with a proxy object, it compareTocalls the TraceHandlerclass invokemethod. The printing method method name and parameters, and then packaging the Integercall on the object compareTo.

Finally, at the end of the sample program, we call

System.out.println(elements[result]);

printlnMethod on the proxy object call toString, and the call can be redirected to a handler is called.

Here is the complete track running:

500.compareTo(288)
250.compareTo(288)
375.compareTo(288)
312.compareTo(288)
281.compareTo(288)
296.compareTo(288)
288.compareTo(288)
288.toString()

You can search interval will be shortened by half in each step to understand the binary search algorithm is how to locate the keys. Note that the toStringmethod is the agent, even though it does not belong to Comparablethe interface, as you will see in the next section, certain Objectmethod is always the proxy.

Listing 6.10 proxy / ProxyTest.java

package proxy;
 
import java.lang.reflect.*;
import java.util.*;
 
/**
* This program demonstrates the use of proxies.
* @version 1.01 2018-04-10
* @author Cay Horstmann
*/
public class ProxyTest
{
   public static void main(String[] args)
   {
      var elements = new Object[1000];
 
      // fill elements with proxies for the integers 1 . . . 1000
      for (int i = 0; i < elements.length; i++)
      {
         Integer value = i + 1;
         var handler = new TraceHandler(value);
         Object proxy = Proxy.newProxyInstance(
            ClassLoader.getSystemClassLoader(),
            new Class[] { Comparable.class } , handler);
         elements[i] = proxy;
      }
 
      // construct a random integer
      Integer key = new Random().nextInt(elements.length) + 1;
 
      // search for the key
      int result = Arrays.binarySearch(elements, key);
 
      // print match if found
      if (result >= 0) System.out.println(elements[result]);
   }
}
 
/**
* An invocation handler that prints out the method name and parameters, then
* invokes the original method
*/
class TraceHandler implements InvocationHandler
{
   private Object target;
 
   /**
    * Constructs a TraceHandler
    * @param t the implicit parameter of the method call
    */
   public TraceHandler(Object t)
   {
      target = t;
   }
 
   public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
   {
      // print implicit argument
      System.out.print(target);
      // print method name
      System.out.print("." + m.getName() + "(");
      // print explicit arguments
      if (args != null)
      {
         for (int i = 0; i < args.length; i++)
         {
            System.out.print(args[i]);
            if (i < args.length - 1) System.out.print(", ");
         }
      }
      System.out.println(")");
 
      // invoke actual method
      return m.invoke(target, args);
   }
}

6.5.3 proxy class properties

Now that you have seen the role of the proxy class, so let's examine some of their properties. Remember, the proxy class is in the running program created dynamically. However, once they are created, they are just regular class, just like any other virtual machine in the same category.

All proxy classes extend the class Proxy. Only one instance of a proxy class field - the invocation handler, it is in the Proxysuper class definition. Any other data required to perform the tasks proxy object must be stored in the call handler. For example, when our agents in the program shown in Listing 6.10 Comparableobject, the TraceHandlerpackaging of the actual object.

All proxy classes override Objectclasses toString, equalsand hashCodemethods. As with all proxy methods that simply calling on the call handler invoke. ObjectOther methods (e.g., class cloneand getClass) are not redefined.

Name of the proxy class is not defined. Oracle virtual machine Proxyclass string generated $Proxyclass names begin with.

For a particular class loader and ordered set of interfaces, only a proxy class. In other words, if the same class loader and an array of interfaces called twice newProxyInstancemethods, it will get two objects of the same class. You can also use the getProxyClassmethod to get the class:

Class proxyClass = Proxy.getProxyClass(null, interfaces);

Proxy class is always publicand final. If the proxy class implements all interfaces are public, the agent class does not belong to any particular package. Otherwise, all the non- publicinterface must belong to the same package, the proxy class also belongs to the package.

By calling the Proxyclass isProxyClassmethod, we can test specific Classwhether the object represents a proxy class.

java.lang.reflect.InvocationHandler 1.3

  • Object invoke(Object proxy, Method method, Object[] args)
    This method is defined to include the action that you want performed when the call to the proxy object.

java.lang.reflect.Proxy 1.3

  • static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
    Returns the proxy class to the given interface.
  • static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
    Configured to implement a new instance of the proxy class for a given interface. All of which invoke the given handler object invokemethod.
  • static boolean isProxyClass(Class<?> cl)
    If cla proxy class is returned true.

The final chapter describes the object-oriented features of the Java programming language. Interfaces, lambda expressions, and inner classes is that you often encounter the concept of cloning, loader and proxy service is an advanced technology, they are primarily of interest to designers and tools to build the library, rather than the application programmer. The program is now in the unusual circumstances you're ready to learn how to deal with in Chapter 7.

Guess you like

Origin blog.csdn.net/nbda1121440/article/details/91360166