If the proxy class already exists before the program is run, then the proxy is used as a static proxy, in which case the proxy class is usually defined in Java code. Typically, proxy classes and delegate classes in a static proxy implement the same interface or derive from the same parent class.
I. Overview
1. What is an agent
We all know that the micro-business agent, simply is to replace the manufacturers to sell goods, manufacturers "commissioned" agent for its sales of goods. About the micro-business agent, first of all, when we buy things from them, we usually do not know who is behind the manufacturer, in other words, the "principal" for us is not visible, and secondly, the micro-business agent mainly in the circle of friends as the target customers, which is equivalent to the manufacturers do a group of customers to "filter." We further abstract the agent and the manufacturers, the former can be abstracted as a proxy class, the latter can be abstracted as a delegate class (by proxy Class). By using proxies, there are usually two advantages and can correspond to the two characteristics of the Micro quotient agent we mentioned:
Advantage One: can hide the implementation of the delegate class;
Merit Two: can realize the decoupling between the client and the delegate class, can do some extra processing without modifying the delegate class code.
2. Static proxy
If the proxy class already exists before the program is run, then the proxy is used as a static proxy, in which case the proxy class is usually defined in Java code. Typically, proxy classes and delegate classes in a static proxy implement the same interface or derive from the same parent class. Below we use the vendor class to represent the manufacturer, the Businessagent class represents the micro-quotient agent, to introduce the static proxy simple realization, the delegate class and the proxy class all implements the Sell interface, the Sell interface definition is as follows:
public interface Sell {void Sell (); void ad ();
}
The vendor class is defined as follows: Public
class Vendor implements Sell {public void Sell () {
System.out.println (' in Sell method ');
} public void ad () {
system,out.println (' ad method ')
}
}
The proxy class businessagent is defined as follows:
public class vendor implements Sell {public void Sell () {
System.out.println (' in Sell method ');
} public void A D () {
system,out.println ("ad method")
}
}
From the definition of the Businessagent class, we can see that static agents can be implemented by aggregation, so that the proxy class holds a reference to the delegate class.
Let's consider this requirement: Add a filtration function to the vendor class, only sell the goods to college students. With static proxies, we do not need to modify the code of the vendor class to implement it, just add a judgment to the Sell method in the Businessagent class as follows:
public class Businessagent implements Sell {
...
public void Sell () {
if (iscollegestudent ()) {
Vendor.sell (
)}} ...
}
This corresponds to the second advantage we mentioned above for using the broker: It enables decoupling between the client and the delegate class, and can do some extra processing without modifying the delegate class code. The limitation of static agent is that the proxy class must be written before running, and we will focus on the dynamic proxy method of generating proxy class under runtime.
Second, dynamic agent
1. What is a dynamic proxy
proxy classes that are created when the program is run are made dynamic proxies. That is, in this case, the proxy class is not defined in Java code, but is dynamically generated at run time according to our instructions in Java code. Compared with static proxy, the advantage of dynamic agent is that it can easily handle the function of proxy class, without modifying the function of each proxy class. So to speak more abstract, we combine an example to introduce the dynamic agent of this advantage is how to embody.
Now, suppose we want to implement a requirement that outputs "before" before executing the method in the delegate class, and then outputs "after" at the end of execution. We also use the vendor class in the example above as the delegate class, Businessagent class as a proxy class to introduce. First we use a static proxy to implement this requirement, and the relevant code is as follows:
public class Businessagent implements Sell {
private vendor Mvendor;
Public businessagent (Vendor vendor) {
This.mvendor = Vendor;
}
public void Sell () {
System.out.println ("before");
Mvendor.sell ();
System.out.println ("after");
}
public void ad () {
System.out.println ("before");
Mvendor.ad ();
System.out.println ("after");
}
From the above code we can understand that through the static proxy to achieve our needs, we need to add the corresponding logic in each method, there are only two methods so the workload is not large, if the sell interface contains hundreds of methods? Using static proxies at this time will write many redundant code. By using dynamic proxies, we can do a "uniform instruction" to unify the methods of all proxy classes without modifying each method individually. Here are a few details on how to use the dynamic proxy approach to achieve our needs.
2. Using dynamic proxies
(1) Invocationhandler interface
When using dynamic proxies, we need to define a mediation class located between the proxy class and the delegate class, which is required to implement the Invocationhandler interface, which is defined as follows:
Public interface Invocationhandler {
object Invoke (Object proxy, Method method, object[] args);
From the name of Invocationhandler, we can know that the mediation class that implements this interface is used as the "call processor". When we call a method of a proxy class object, the call is forwarded to the Invoke method, and the proxy class object is passed in as a proxy parameter, which identifies the method in which we specifically invoke the proxy class, args as the parameter of the method. In this way, our invocation of all the methods in the proxy class becomes a call to invoke, so that we can add a unified processing logic to the Invoke method (or do different processing of the different proxy class methods according to the method parameters). So we simply output "before" in the invocation method implementation of the mediation class, then invoke the delegate class and then output "after". Here we go step-by-step to achieve it concretely.
(2) The definition of the delegate class
The dynamic proxy method requires that the delegate class must implement an interface, where we implement the Sell interface. The delegate class vendor class is defined as follows:
public class vendor implements Sell {public
void Sell () {
System.out.println (' in Sell method ');
}
public void ad () {
system,out.println (' ad method ')
}
}
(3) Intermediary class
As we mentioned above, the mediation class must implement the Invocationhandler interface as a call to the calling processor "intercept" the proxy class method. The mediation class is defined as follows:
public class Dynamicproxy implements Invocationhandler {
private object obj;//obj as a delegate class object;
Public dynamicproxy (Object obj) {
this.obj = obj;
}
@Override Public
object Invoke (Object proxy, Method method, object[] args) throws Throwable {
System.out.println ("before");
Object result = Method.invoke (obj, args);
System.out.println ("after");
return result;
}
As we can see from the above code, the mediation class holds a delegate class object reference, and the corresponding method of the delegate class object is called in the Invoke method (line 11th). Holding delegate class object references through aggregation The call to the delegate class object is eventually converted to the invocation of the external invoke. Isn't that a way to implement the static proxy we described above? In fact, the intermediary class and the delegate class constitute a static agent relationship, in this relationship, the intermediary class is the proxy class, the delegate class is the delegate class; The proxy class and the Mediation class also form a static proxy relation, in this relation, the intermediary class is the delegate class, the proxy class is the proxy class. In other words, dynamic agent relationship consists of two sets of static agent relationship, which is the principle of dynamic agent. Here's how to "indicate" to dynamically generate the proxy class.
(4) Dynamic generation of proxy class
The related code for the dynamically generated proxy class is as follows:
public class Main {public
static void Main (string[] args) {
//Create Mediation class instance
dynamicproxy inter = new Dynamicproxy (n EW vendor ());
Adding this sentence will produce a $proxy0.class file, which is the dynamically generated proxy class file
system.getproperties (). Put (" Sun.misc.ProxyGenerator.saveGeneratedFiles "," true ");
Gets the proxy class instance Sell
Sell Sell = (Sell) proxy.newproxyinstance (Sell.class.getClassLoader (), new class[] {Sell.class}, inter));
Invoking the proxy class method through the proxy class object will actually go to the Invoke method invocation
Sell.sell ();
Sell.ad ();
}
In the above code, we call the Newproxyinstance method of the proxy class to get a proxy class instance. This proxy class implements the interface we specify and distributes the method call to the specified calling processor. The declaration of this method is as follows:
Copy Code code as follows:
public static Object newproxyinstance (ClassLoader loader, class<?>[] interfaces, Invocationhandler h) throws IllegalArgumentException
The three parameter meanings of the method are as follows:
Loader:Defines the classloder of the proxy class;
Interfaces:List of interfaces implemented by proxy class
h:Call the processor, which is the class instance that we defined above to implement the Invocationhandler interface.
Let's run around and see if our dynamic agents work properly. The output I run here is:
This means that our dynamic agent really works.
Above we have simply mentioned the principle of dynamic agent, here is a simple summary: first through the Newproxyinstance method to get proxy class instances, and then we can invoke the proxy class through the proxy class instance of the method, calls to the proxy class method will actually call the mediation class (call the processor Invoke method, in which we invoke the corresponding method of the delegate class, and we can add our own processing logic.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.