Java dynamic proxy analysis (including static agent)

Proxy Mode: provide an access control an object proxy for other objects. Used: In some cases, a customer does not want or can not directly access another object, the proxy object can play the role of intermediary before the client and the target object, the proxy object can complete its additional operations.

 

Examples: relationship is like the landlord, tenant, broker. After intermediary (proxy object) for the landlord (real object) rent house tenants (customers) through an intermediary (proxy object) to find a house to rent, the rental agency may charge a complete agency fee (additional operations).

 

Take a look at a static proxy mode, on the face of the understanding proxy mode, you can understand proxy mode: that is, not directly through the new method to invoke a real object, but to call a method through a proxy object, the proxy object that contains real object references. Let's look at the code

Interface: Subject contains a method

1 package com.example.designpattern.proxy;
2 
3 public interface Subject {
4 void request();
5 }

RealSubject class that implements the Subject interface sake of simplicity, the simple sentence output:

. 1  Package com.example.designpattern.proxy;
 2  
. 3  public  class RealSubject the implements the Subject {
 . 4  // really achieve a role 
. 5  public  void Request () {
 . 6 System.out.println ( "Subject the From Real" );
 . 7  }
 . 8 }

 

Acting classes ProxySubject, but also to achieve Subject interfaces, Subject inside the method to achieve, but here there is a real object by calling achieved.

. 1  Package com.example.designpattern.proxy;
 2  
. 3  public  class ProxySubject the implements the Subject {
 . 4  
. 5  Private RealSubject RealSubject; // proxy roles within the true character references
 . 6  
. 7  // agent to achieve the target operating roles 
. 8  public  void Request () {
 . 9  
10  the this .preRequest (); // before the real operation role additional operations 
. 11  IF (RealSubject == null ) {
 12 is RealSubject = new new RealSubject ();
 13 is  }
 14realSubject.request (); // true roles things done 
15  the this .afterRequet (); // after the operation of the real role of additional operations 
16  }
 17  // completed before the agent role of an operation 
18 is  Private  void preRequest () {
 . 19 System.out.println ( "pre Request" );
 20 is  }
 21 is  // completed character after the operation of the agent 
22 is  Private  void afterRequet () {
 23 is System.out.println ( "after Request" );
 24  }
 25 }

Customer caller

package com.example.designpattern.proxy;

public class Client {
public static void main(String[] args) {
Proxy ProxySubject = new new ProxySubject ();
 // to invoke methods through the proxy object 
proxy.request ();
}
}

 

Static proxy:
you can run the code Oh, you can see the Client class, is through target proxy proxy ProxySubject to call the method in the proxy class ProxySubject, there is a reference to a real object, the request in a proxy object ( ) method calls a method of real objects. This mode is called proxy mode.

The advantages are:
the target object 1. The agent mode can proxy object and real object is called separation.
2. reduced to some extent on the degree of coupling system, good scalability.

Acting class contains a reference to the real topic, this also has disadvantages :
1. The real object correspond with the proxy class, the class should be increased to increase the real proxy class, this will rapidly increase the number of classes, so that the system becomes complex.
2. Design agency before the real theme must already exist, less flexible.


Dynamic agents can solve the above problem, the dynamic proxy is a proxy for the relative static.

You might also say how dynamic to create an instance, we used to create instances are not achieved through new way of it?

// as 
the Hello Hi = new new the Hello ();

Then dynamically create an instance is provided by the Java function, you do not need us to new objects, he has defined the static method Proxy.newProxyInstance (), as long as you can pass parameters to call. Oh Java documentation which has, as shown:

 

Java standard library provides a dynamic proxy (DynamicProxy) mechanism: you can create an instance of an interface dynamically at runtime.
Parameters explanation:

. 1  the Proxy.newProxyInstance (
 2 ClassLoader Loader, // passing ClassLoader 
. 3 <?> Class [] the interfaces, // passing the interface to call methods array 
. 4 ; InvocationHandler H) // example of incoming InvocationHandler


The following look at the dynamic proxy sample code:
Subject Interface

package design.dynamicproxy;

public interface Subject {
void request(String str);
}

 

Subject RealSubject class implements the interface

1 package design.dynamicproxy;
2 
3 public class RealSubject implements Subject {
4 @Override
5 public void request(String str) {
6 System.out.println("From Real Subject!" + " args:" + str );
7 }
8 }

 

DynamicSubject dynamic proxy class implements InvocationHandler, rewriting invoke () method

. 1  Package design.dynamicproxy;
 2  
. 3  Import java.lang.reflect.InvocationHandler;
 . 4  Import the java.lang.reflect.Method;
 . 5  
. 6  / ** 
. 7  * internal properties of the proxy class of type Object, in practical use, the use of class constructor to pass an object
 8  * further class also implements invoke () method, the method Method.invoke () to call a method to actually execute the proxy object
 9  * object method parameters, indicating that the the method object subordinate objects, dynamic proxy class, we can perform really object
 10  may add some additional methods longitudinal method *
 . 11  * / 
12 is  public  class DynamicSubject the implements of InvocationHandler {
 13 is  
14  // type object is introduced to be just pass any object 
15 Private Object Object;
 16  
. 17  public DynamicSubject (Object Object) {
 18 is  the this .Object = Object;
 . 19  }
 20 is  
21 is  @Override
 22 is  public Object Invoke (Object Proxy, Method, Method, Object [] args) throws the Throwable {
 23 is the System.out. the println ( "calling before:" + method);
 24  // equivalent realSubject the request () method, if there is not invoked, then the method does not call method object 
25  Method.invoke (Object, args);
 26 is the System .out.println ( "Calling After:" + Method);
 27  return  null ;
28 }
29 }

 

Client class

 1 package design.dynamicproxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5 
 6 public class Client {
 7 
 8 public static void main(String[] args) {
 9 RealSubject realSubject = new RealSubject();
10 InvocationHandler handler = new DynamicSubject(realSubject);
11 Class<?> classType = handler.getClass();
12 //下面的代码一次性生成代理
13 //Examples of the dynamically generated class com.sun.proxy of $ Proxy0,. 
14 the Subject Subject = (the Subject) the Proxy.newProxyInstance (classType.getClassLoader (), realSubject.getClass () The getInterfaces (), Handler.);
 15 subject.request ( "Eather" );
 16 System.out.println (subject.getClass ()); // . output class com.sun.proxy $ Proxy0, you can see the Proxy.newProxyInstance () is an example of automatically generated 
17  }
 18 }

 

Client can see, we here call the method is subject.request ( "eather"); the object is not subject generated by new DynamicSubject () method instead of Java to write dynamically generated inside objects at runtime; possible someone said

InvocationHandler handler = new DynamicSubject(realSubject);


This is not by new new DynamicSubject (realSubject); generating an object? Yes, but it is InvocationHandler type, primarily pass a type parameter to the Proxy.newProxyInstance InvocationHandler (); i.e., the last parameter. You can see by the last sentence of the output of the Client class which is class com.sun.proxy. $ Proxy0, which is generated by the Java runtime.

Static agent to solve the problem: 1 real object and the proxy class one to one, real class should be increased to increase the proxy class, doing so rapid increase in the number of classes will make the system more complicated. Why do you say, because the agent class reference type is Object, you can easily pass any object, when the increase in real class, proxy class do not increase, new DynamicSubject (object); new time to pass the object to be passed go to.

Here is Proxy.newProxyInstance (ClassLoader loader, Class [] interfaces, InvocationHandler h <?>); The source of this approach it, you can see, a closer look

 1 public static Object newProxyInstance(ClassLoader loader,
 2 Class<?>[] interfaces,
 3 InvocationHandler h)
 4 throws IllegalArgumentException
 5 {
 6 Objects.requireNonNull(h);
 7 
 8 final Class<?>[] intfs = interfaces.clone();
 9 final SecurityManager sm = System.getSecurityManager();
10 if (sm != null) {
11 checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
12 }
13 
14 /*
15  . * Look up or Generate The Designated Proxy class
 16  generates a proxy class object
 . 17  * / 
18 is Class Cl = <?> GetProxyClass0 (Loader, intfs);
 . 19  
20 is  / * 
21 is  * the Invoke ITS constructor with The Designated Invocation Handler.
 22 is  using the specified invocation handler calls its constructor. [Example InvocationHandler call is used to call a method of that class constructor]
 23 is  * / 
24  the try {
 25  IF (SM =! Null ) {
 26 is  checkNewProxyPermission (Reflection.getCallerClass (), Cl);
 27  }
 28  
29  Final the Constructor < ?> cons = cl.getConstructor(constructorParams);
30 final InvocationHandler ih = h;
31 if (!Modifier.isPublic(cl.getModifiers())) {
32 AccessController.doPrivileged(new PrivilegedAction<Void>() {
33 public Void run() {
34 cons.setAccessible(true);
35 return null;
36 }
37 });
38 }
39 return cons.newInstance(new Object[]{h});
40 } catch (IllegalAccessException|InstantiationException e) {
41 throw new InternalError(e.toString(), e);
42 } catch (InvocationTargetException e) {
43 Throwable t = e.getCause();
44 if (t instanceof RuntimeException) {
45 throw (RuntimeException) t;
46 } else {
47 throw new InternalError(t.toString(), t);
48 }
49 } catch (NoSuchMethodException e) {
50 throw new InternalError(e.toString(), e);
51 }
52 }

 

Guess you like

Origin www.cnblogs.com/eathertan/p/12457862.html