Static proxy and dynamic proxy
The so-called proxy Design refers to the operation of a real subject by a proxy subject, and the actual subject executes specific business operations, while the proxy subject is responsible for the processing of other related businesses.
This is often the case in the system: verification is required before some operations, such as advanced user information verification when adding or deleting operations, to check whether the user has permissions for these operations. The Code is as follows:
// UserManager interface: public interface UserManager {public void addUser (String username, String password); public void delUser (int userId);} // UserManagerImpl class to implement the UserManager interface: public class UserManagerImpl implements UserManager {public void addUser (String username, String password) {checkSecurity (); System. out. println ("--------- UserManagerImpl. add () -------- ");} public void delUser (int userId) {checkSecurity (); System. out. println ("--------- UserManagerImpl. delUser () -------- ");} private void checkSecurity () {System. out. println ("------- checkSecurity -------");}}
When the verification function checkSecurity () is added to the Add/delete method, the problem arises. If the verification function checkSecurity () needs to be added to hundreds of functions, hundreds of checkSecurity () are required () function. If the requirement changes one day and user verification is not required, you need to delete checkSecurity () from hundreds of functions, resulting in poor maintainability. How can this problem be solved?
1. Static proxy
Add proxy class
Public class UserManagerImpl implements UserManager {public void addUser (String username, String password) {// checkSecurity (); System. out. println ("--------- UserManagerImpl. add () -------- ");} public void delUser (int userId) {// checkSecurity (); System. out. println ("--------- UserManagerImpl. delUser () -------- ");} // private void checkSecurity () {// System. out. println ("------- checkSecurity -------"); //} // UserManagerImplProxy proxy class: (Note: This proxy class can only serve UserManager APIs) public class UserManagerImplProxy implements UserManager {private UserManager userManager; public UserManagerImplProxy (UserManager userManager) {this. userManager = userManager;} public void addUser (String username, String password) {checkSecurity (); userManager. addUser (username, password);} public void delUser (int userId) {checkSecurity (); userManager. delUser (userId);} private void checkSecurity () {System. out. println ("------- checkSecurity -------");}}
Static Proxy:
Proxy class -- created during compilation, UserManagerImplProxy can only serve the UserManager interface;
Adding or deleting a proxy class ensures that the target function is not changed and the maintainability is enhanced. However, the root problem is not solved because the problem is transferred to the proxy class, the problems mentioned above still exist. How can this problem be solved?
2. Dynamic Proxy:
Take out a total of checkSecurity () Verification and place it in a separate class;
Proxy class-created at runtime, which can serve each interface;
Dynamic proxy considerations: place independent services (cross-cutting services) distributed in the system in one place and automatically place them at runtime. Horizontal issues are considered;
Code:
// UserManager interface public interface UserManager {public void addUser (String username, String password); public void delUser (int userId );} // UserManagerImpl class implements the UserManager interface public class UserManagerImpl implements UserManager {public void addUser (String username, String password) {// checkSecurity (); System. out. println ("--------- UserManagerImpl. add () -------- ");} public void delUser (int userId) {// checkSecurity (); System. out. println ("--------- UserManagerImpl. delUser () -------- ");} // private void checkSecurity () {// System. out. println ("------- checkSecurity -------"); //} import java. lang. reflect. invocationHandler; import java. lang. reflect. method; import java. lang. reflect. proxy; // The interface InvocationHandlerpublic class SecurityHandler implements InvocationHandler {private Object targetObject; // target class, create Proxy class based on the target // create Proxy class public Object createProxyInstance (Object targetObject) export this.tar getObject = targetObject; // generate Proxy based on the target // parameter: 1st parameters: Agent class loading Proxy class; 2nd parameters: Target Interface; 3rd parameters: return Proxy. newProxyInstance (targetObject. getClass (). getClassLoader (), targetObject. getClass (). getInterfaces (), this);} public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {checkSecurity (); // call the target method Object ret = Method. invoke (targetObject, args); return ret;} private void checkSecurity () {System. out. println ("------- checkSecurity -------") ;}// Client public class Client {public static void main (String [] args) {SecurityHandler hander = new SecurityHandler (); // generate the proxy UserManager userManager = (UserManager) hander. createProxyInstance (new UserManagerImpl (); userManager. addUser ("zhangsan", "123"); // call the ddUser () method }}
3. Summary
Static proxy usually only acts as a proxy for one class. Dynamic proxy is used to represent multiple implementation classes under an interface.
The static proxy knows in advance what the proxy is, but the dynamic proxy does not know what the proxy is, and it is only known at runtime.
Dynamic proxy is the invoke method that implements the InvocationHandler interface in JDK, but note that the proxy is an interface, that is, your service class must implement the interface, obtain the Proxy object through newProxyInstance in Proxy.
There is also a dynamic proxy CGLIB. The proxy is a class, and the business class inheritance interface is not required. The derived subclass is used to implement the proxy. You can modify the class by dynamically modifying the bytecode at runtime.