Last article we wrote about static agents Agent mode of design mode [1] static agent
Let's talk about java's dynamic proxy today.
1, Why use dynamic proxy
In fact, the dynamic agent makes up for the shortcomings of the static agent. The static agent needs to write a proxy class for each proxy object, which requires a lot of redundant code. The dynamic agent only needs to write a proxy class, which can proxy multiple different objects and greatly reduce duplicate code, provided that they realize the same interface.
Keep in mind that the primary purpose of proxies is to control access to the target object, not to enhance the functionality of the target object. Access control includes synchronization, authentication, remote access (RPC), lazy instantiation (Hibernate, Mybatis), AOP (transaction).
2, Dynamic agent implementation
2.1 jdk dynamic agent
First of all, let's set a scene. For example, I want to go on a blind date with Xiaohua, but I can't contact Xiaohua directly. I need to introduce my matchmaker to date Xiaohua.
At this time, floret is the proxy object, the matchmaker is the proxy object, I am the initiator of the program.
Date interface: two functions, watching movies and having lunch
package com.example.demo1.Dynamic; //Define interface appointment public interface YueHui { //watch movie void movie(); //to have lunch void lunch(); }
Xiaohua: implement the date interface
/** * Object floret * Need to implement appointment interface * create by c-pown on 2020-06-29 */ public class XiaoHua implements YueHui { @Override public void movie() { System.out.println("Watch a movie with xiaohua"); } @Override public void lunch() { System.out.println("Lunch with xiaohuakan"); } }
Proxy object (matchmaker) core: it implements the InvocationHandler interface and rewrites the invok e method, calls the object method through reflection, and can enhance the context.
The getObj() method can return an interface implementation object.
/** * Agent matchmaker * The InvocationHandler interface needs to be implemented * create by c-pown on 2020-06-29 */ public class ProxyPerson implements InvocationHandler { //Objects to be represented (general) private Object object; //Create constructor public ProxyPerson(Object object) { this.object = object; } // Parameter Description: // Proxy: dynamic proxy object (that is, which dynamic proxy object calls method() // Method: the method called by the target object // args: Specifies the parameters of the called method @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //The agent methods can be enhanced here, such as adding transactions, wrapping before and after, etc System.out.println("Ask for parental consent in advance"); method.invoke(object,args); System.out.println("Report results to parents"); return null; } //Return interface implementation //Here this:: invoke can be omitted as this, which means executing the invoke method public Object getObj(){ return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this::invok); } }
Test main class: we need to initialize the proxy object into the proxy object, and then directly return the interface object and call the method.
/** * Test dynamic agents * create by c-pown on 2020-06-29 */ public class TestDynamicProx { public static void main(String[] args) { //Objects that need to be proxied XiaoHua xiaoHua = new XiaoHua(); //Will need to be proxy object, pass to proxy object ProxyPerson proxyPerson = new ProxyPerson(xiaoHua); //Return interface implementation YueHui yueHui = (YueHui)proxyPerson.getObj(); yueHui.lunch(); yueHui.movie(); } }
Implementation results:
Ask for parental consent first Lunch with xiaohuakan Report results to parents Ask for parental consent in advance Watching movies with xiaohua Report results to parents
The agent is implemented and enhanced.
If Xiaohua and I are not satisfied, the matchmaker introduces a new girl, Xiaojing.
At this time, we don't need to write a proxy class for Xiaojing, we just need to implement the appointment interface;
/** * New object Xiaojing * Need to implement appointment interface * create by c-pown on 2020-06-29 */ public class XiaoJing implements YueHui { @Override public void movie() { System.out.println("Watching movies with Xiaojing"); } @Override public void lunch() { System.out.println("Lunch with Xiaojing"); } }
The same proxy object can proxy different objects multiple times.
package com.example.demo1.Dynamic; /** * Test dynamic agents * create by c-pown on 2020-06-29 */ public class TestDynamicProx { public static void main(String[] args) { //Objects to be proxied XiaoHua xiaoHua = new XiaoHua(); //Pass the object to be represented to the proxy object ProxyPerson proxyPerson = new ProxyPerson(xiaoHua); //Return interface implementation YueHui yueHui = (YueHui)proxyPerson.getObj(); yueHui.lunch(); yueHui.movie(); System.out.println("-------------Dividing line-------------"); //Objects to be proxied XiaoJing xiaoJing = new XiaoJing(); //Pass the object to be represented to the proxy object ProxyPerson proxyPerson1 = new ProxyPerson(xiaoJing); //Return interface implementation YueHui yueHui1 = (YueHui)proxyPerson1.getObj(); yueHui1.lunch(); yueHui1.movie(); } }
result:
Ask for parental consent first Lunch with xiaohuakan Report results to parents Ask for parental consent in advance Watching movies with xiaohua Report results to parents -------------Dividing line------------- Ask for parental consent first Lunch with Xiaojing Report results to parents Ask for parental consent in advance Watching movies with Xiaojing Report results to parents
Well, no matter how many girls there are behind, Xiaomei, Xiaofang, a matchmaker is enough.