Java static proxy and dynamic proxy
First, we will introduce what is proxy:
Proxy mode is a common design mode. The proxy class has the same interface as the delegate class. The proxy class is mainly responsible for preprocessing, filtering, and forwarding messages to the delegate class. And post-processing messages.
There is an association between the proxy class and the delegate class. The proxy class object itself does not actually implement the service. Knowledge calls the relevant methods of the delegate class object.
There are two types of proxies: static proxy and dynamic proxy.
Static Proxy:
A proxy class is created by a programmer or compiled by code generated by a tool. Before running the program, the *. class file of the proxy class already exists. It can be run directly.
Dynamic Proxy:
Dynamic proxy. Not directly generated by source code. Dynamic proxy objects are dynamically generated by the JAVA reflection mechanism when the program is running. You do not need to write the source code manually. This improves the scalability of the software. The JAVA reflection mechanism can generate dynamic proxy classes of any type.
Static proxy implementation:
Interface:
package test.static.pattern;public interface UserManager {public void addUser(String userId,String userName);public void delUser(String userId);public String findUser(String userId);public void modifyUser(String userId,String userNameString);}
Implementation class:
package test.static.pattern;public class UserManagerImpl implements UserManager {@Overridepublic void addUser(String userId, String userName) {System.out.println(UserManagerImpl.addUser() userId-->> + userId);}@Overridepublic void delUser(String userId) {System.out.println(UserManagerImpl.delUser() userId-->> + userId);}@Overridepublic String findUser(String userId) {System.out.println(UserManagerImpl.findUser() userId-->> + userId);return null;}@Overridepublic void modifyUser(String userId, String userNameString) {System.out.println(UserManagerImpl.modifyUser() userId-->> + userId);}}
Static proxy class: (only hold object references)
package test.static.pattern;public class UserManagerImplProxy implements UserManager {private UserManager userManager;public UserManagerImplProxy(UserManager userManager){this.userManager=userManager;}@Overridepublic void addUser(String userId, String userName) {userManager.addUser(userId, userName);}@Overridepublic void delUser(String userId) {userManager.delUser(userId);}@Overridepublic String findUser(String userId) {return userManager.findUser(userId);}@Overridepublic void modifyUser(String userId, String userNameString) {userManager.modifyUser(userId, userNameString);}}
Client:
Package test. static. pattern; public class Client {/*** @ param args */public static void main (String [] args) {// normal idea: userManager userManager = new UserManagerImpl (); // static Proxy: client instantiation proxy, userManager userManager = new UserManagerImplProxy (new UserManagerImpl (); userManager. addUser (0001, Zhang San );}}
Execution result:
Static proxy, because the proxy class holds the reference of the object, it can be controlled.
Symptom 1: for each function module, a corresponding proxy class must be created. Cause a large number of proxies
Symptom 2: If you implement the same control for each implementation, You need to repeat a lot of code.
To avoid repeated codes, we will continue to look at what is dynamic proxy.
Dynamic proxy implementation:
Interface:
package test.dynamic.pattern;public interface UserManager {public void addUser(String userId,String userName);public void delUser(String userId);public String findUser(String userId);public void modifyUser(String userId,String userNameString);}
Implementation class:
package test.dynamic.pattern;public class UserManagerImpl implements UserManager {@Overridepublic void addUser(String userId, String userName) {System.out.println(UserManagerImpl.addUser() userId-->> + userId);}@Overridepublic void delUser(String userId) {System.out.println(UserManagerImpl.delUser() userId-->> + userId);}@Overridepublic String findUser(String userId) {System.out.println(UserManagerImpl.findUser() userId-->> + userId);return null;}@Overridepublic void modifyUser(String userId, String userNameString) {System.out.println(UserManagerImpl.modifyUser() userId-->> + userId);}}
Dynamic proxy generation class:
Package test. dynamic. pattern; import java. lang. reflect. invocationHandler; import java. lang. reflect. method; import java. lang. reflect. proxy; import org. omg. CORBA. systemException; import org. omg. CORBA. portable. inputStream; import org. omg. CORBA. portable. invokeHandler; import org. omg. CORBA. portable. outputStream; import org. omg. CORBA. portable. responseHandler; public class LogHandler implements InvocationHandler {/*** call the Method abstraction of the referenced Object class */@ Overridepublic Object invoke (Object proxy, method Method, Object [] args) throws Throwable {Object ret = null; try {// call the target method ret = method. invoke (targetObject, args);} catch (Exception e) {throw e;} return null;} // reference to the target implementation private Object targetObject; /*** Proxy class Generation Method * @ param targetObject * @ return */public Object newProxyInstance (Object targetobject?#this.tar getObject = targetObject; return Proxy. newProxyInstance (targetObject. getClass (). getClassLoader (), targetObject. getClass (). getInterfaces (), this );}}
Client:
Package test. dynamic. pattern; public class Client {/*** @ param args */public static void main (String [] args) {// dynamic proxy LogHandler logHandler = new LogHandler (); userManager userManager = (UserManager) logHandler. newProxyInstance (new UserManagerImpl (); // userManager. addUser (0001, Zhang San); userManager. delUser (111 );}}
Execution result:
The dynamic proxy class is not reflected in the program. The corresponding proxy class is created only when the program is running. In this way, you can reduce the number of proxy classes. For symptom 2, the same control code is reduced.