Dynamic Agent:
Before you know the dynamic agent, you have an understanding of the agent.
Proxy mode is one of the common design patterns in Java. The so-called proxy pattern is that the client does not invoke the actual object directly, but calls the actual object indirectly by invoking the proxy.
To make an analogy: when you buy a train ticket, do not pay directly to buy, but the money advance to the ticket to rob the software, so that the ticket software for you to buy, you have to do the act is to buy tickets, rob the software is your agent
The proxy object Controls access to the Proxied object:
This is the general model diagram of the agent
Subject: Defines the common interface or abstract class of the agent role and proxy role, that is, the common interface opration () defined in Subject;
Realsubject: Implements or inherits abstract theme roles, defining implementations that implement specific business logic .
Proxy: That is, the agent, Porxy holding Realsubject reference control and implementation. and has its own processing logic.
Agent is divided into static and dynamic two, first understand the static agent, know its shortcomings, then understand the dynamic agent, will be enlightened.
The role of static proxies:
Static proxies are often used to augment legacy business logic. For example, a class that holds a two-party package and calls some of these methods. Then for some reason, such as logging, printing method execution time, but it is not good to write these logic to the two-party package method. So you can create a proxy class implementation and the two-party method the same way, by having the proxy class hold the real object, and then invoke the proxy class method in the original code to achieve the purpose of adding the business logic that we need.
Implementation of static proxies:
It is convenient to understand the introduction of proxy is defined by itself, in the following dynamic agent will use the proxy provided in the Java.reflect
package proxy; //将业务层抽象出来的接口.public interface Subject { void doSomething();}
package proxy;//真实对象,也就是被代理者,理解为你自己就可以了,要进行买票行为.public class RealObject implements Subject{ @Override public void doSomething() { System.out.println("这里是真实对象"); }}
package proxy;//代理者,进行代理事务的人,理解成抢票软件,要代替你进行买票行为.public class Proxy implements Subject{ private Subject realObject; Proxy(Subject realObject){ this.realObject=realObject; //从这里知道需要代理的人是谁 } @Override public void doSomething() { System.out.println("这里是代理对象"); //可以在调用真实对象前增加操作 //例如在开抢前告诉你,抢票要开始了. realObject.doSomething();//在这里调用真实的代理对象 //可以在调用真实对象后增加操作. //在抢票结束后,告诉你成功或者失败. } }
Perform:
package proxy;public class ProxyTest { public static void main(String[] args){ RealObject realObject =new RealObject(); realObject.doSomething();//被代理对象做的事,或者说委托人想要做的事 System.out.println("-----------------"); Proxy proxy =new Proxy(new RealObject());//告知代理对象被代理对象是谁,或者说告诉执行者委托人要做什么. proxy.doSomething();//通过代理对象调用被代理对象,实现代理. /* 代理和被代理是不是有点晕,换一种说法来说. 以DOTA为例: 大哥本来要自己拉野,忽然发现一大波线袭来,于是就和酱油说,帮我拉两波野,一会带你喝汤! 大哥就是被代理者 酱油说: 是大哥! 酱油在去拉野的路上,吃了赏金符,拉完野之后配合队友杀了一波人. 酱油就是代理者 吃赏金符就是预处理. 杀人就是结果处理. */ }}
We have found that, although the formation of agent behavior, but the wording of hate, coupling is very high, now is a train ticket, if there are air tickets, concert tickets and so a series of demand and a series of employers, will lead to more and more Code agent class, and there will be the danger of duplicate name, this is the disadvantage of static agent.
In order to solve this problem, the Big brothers invented the dynamic agent method.
Java provides us with a dynamic agent interface, very convenient to use, below to understand.
The functionality to be extended is written in a Invocationhandler implementation class:
The Invoke method in this handler implements the public function to be extended by the proxy class.
Disadvantages of static proxies:
There are 10 different realobject, at the same time we have to go agent method is different, than to proxy method: DoSomething, Doanotherthing, dotwoanotherthing.
Method 1: Create a proxy class for each agent, which causes several classes
Method 2: In a proxy class to create several proxy methods, when the proxy method is more and more prone to cause the code in the proxy class more and more large and have the risk of duplicate name.
For this reason the dynamic agent was born:
Use of dynamic agents:
First look at the interface of the dynamic agent:
- Implementing the Invocationhandler Interface
Let's look at the structure of the interface:
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; //这个接口只有一个方法 就是invoke方法,也就是说我们只要实现invoke方法就可以了}
Although this parameter does not require us to pass, but still need to understand, the first is an instance of the proxy class, the second is the method, the third is the object's parameter array.
2. Create a proxy instance by using the Newproxyinstance method:
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 通过这个方法返回我们代理类的实例, 也就是RealObject的Proxy返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序
The first argument from the parameter is the ClassLoader, the second method is a class object array interface, the third parameter is the Invocationhandler we implemented above
Here does not post the source code, has the interest to be able to trace oneself or to view below my reference material.
Dynamic Proxy instances:
The class that inherits the static proxy above, only the test class and the processing class are written below.
Processing class:
import java.lang.reflect.Proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class DynamicProxyHandler implements InvocationHandler { private Object realObject; Object bind(Object realObject){ this.realObject=realObject;//给真实对象赋值 return Proxy.newProxyInstance(realObject.getClass().getClassLoader(), realObject.getClass().getInterfaces(), this); //通过Class对象得到该对象的构造器,接口方法数组,传入自己构造后的实例. //java.reflect.Proxy方法最后返回的是一个代理实例. } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在这里拓展代理逻辑 System.out.println("rua!"); Object result= method.invoke(realObject,args);//方法的调用. //这里的invoke调用是java进行调用,proxy对象,方法,和参数数组已经是我们之前传入的被代理类的了. return result; }}
Test class:
public class DynamicProxy { public static void main(String[] args){ DynamicProxyHandler pHandler=new DynamicProxyHandler();//创建我们动态代理处理类的对象 Subject proxy=(Subject)pHandler.bind(new RealObject());//对其进行动态代理的参数绑定然后返回一个代理实例 proxy.doSomething();//调用 }}
The first time I looked at the time is also foggy, do not understand why this is dynamic, the method call here, are not related to the method object, not directly called.
No matter what interface you define in subject, it is irrelevant to the call, relying on reflection to get your methods, parameters, classes of data in real time, and then call them through reflection.
There are 10 different realobject, at the same time we have to go agent method is different, than to proxy method: DoSomething, Doanotherthing, dotwoanotherthing.
In this example, I pass in 10 different objects, the object naturally has its own implementation, I through the reflection to achieve after the implementation of the new object, no impact on the original object, and then the new object method call operation, to 100 1000 objects also can.
All of the above conditions are based on reflection, if the reflection is not clear, please return to see the reflection, my blog is also written, can also be understood through the network.
Resources:
1.77584832
2.https://www.zhihu.com/question/20794107/answer/23330381
3.Thinking in Java page 592-598
Java fundamentals-static proxies and dynamic proxies