Static proxy

Static proxy role analysis Abstract role: Interfaces or abstract classes are used to implement real roles. Proxy role: Proxy role. After a real role is represented, it usually performs some ancillary operations. Customer: Uses the proxy role to perform some operations.

Code implementation

Rent.java is an abstract role

/** * @author: zhangh * @date: 2020/11/30 9:31 */ public interface Rent {void Rent (); }Copy the code

1.2. Host. Java is a real role

/** * @description landlord * @author: zhangh * @date: 2020/11/30 9:30 */ public implements Rent {@override public void Rent () {system.out.println (" implements Rent "); }}Copy the code

1.3 Proxy. Java is the Proxy role

/** * @description advantages: Static proxy can make real role operations more pure, no need to pay attention to some subordinate operations (subordinate operations to agent role) * disadvantages: a real role can create a proxy role, the amount of code can double inefficient * @author: zhangh * @Date: 2020/11/30 9:33 */ public class Proxy implements Rent { private Rent rent; public Proxy(Rent rent) { this.rent = rent; } public Proxy() { } @Override public void rent() { a(); rent.rent(); b(); } public void a() {system.out.println (); } public void b() {system.out.println (); }}Copy the code

1.4. Client.java is a Client

/** * @Description * @Author: zhangh * @Date: 2020/11/30 9:33 */ public class Test { public static void main(String[] args) { Rent host = new Host(); Proxy proxy = new Proxy(host); proxy.rent(); }}Copy the code

2. Static proxy test:

/** * @Description * @Author: zhangh * @Date: 2020/11/30 9:33 */ public class Test { public static void main(String[] args) { Rent host = new Host(); Proxy proxy = new Proxy(host); proxy.rent(); }}Copy the code

The results are as follows:

This is done statically through the Proxy class.

3. Benefits of static proxies

Can make our real role more pure. No longer pay attention to some public things. The common business is completed by the agent. The division of business is realized, and the common business becomes more centralized and convenient when it is expanded. Disadvantages: more classes, more proxy classes, the amount of work becomes larger. Development efficiency is reduced.

3.1. Understand static proxy again

3.1.1 create an abstract role, for example, we usually do user business, abstract is to add, delete, change and check!

Public interface UserService {void add(); void delete(); void update(); void query(); }Copy the code

3.2.2 We need a real object to complete these add, delete, change and check operations

// Real object, Public class UserServiceImpl implements UserService {public void add() {system.out.println (" add a user "); } public void delete() {system.out.println (" delete a user "); } public void update() {system.out.println (" update a user "); } public void query() {system.out.println (" query a user "); }}Copy the code

3.3.3 requirements come, now we need to add a log function, how to achieve!

Idea 1: Add code to the implementation class. Idea 2: Using proxies is the best way to do this without changing the business.

3.3.4. Set up a proxy class to handle logging! The agent role

Public class UserServiceProxy implements UserService {private UserServiceImpl UserService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } public void add() { log("add"); userService.add(); } public void delete() { log("delete"); userService.delete(); } public void update() { log("update"); userService.update(); } public void query() { log("query"); userService.query(); } public void log(String MSG){system.out.println (" + MSG +"); }}Copy the code

3.3.5 Test Access Class:

Public class Client {public static void main(String[] args) {// Real service UserServiceImpl userService = new UserServiceImpl(); // UserServiceProxy proxy = new UserServiceProxy(); // Use proxy classes to implement logging! proxy.setUserService(userService); proxy.add(); }}Copy the code

Dynamic proxy

The roles of dynamic proxies are the same as those of static proxies. The proxy classes for dynamic proxies are dynamically generated. Dynamic proxy is divided into two classes: one is based on the interface dynamic proxy, one is based on the class dynamic proxy based on the interface dynamic proxy — JDK dynamic proxy based on the class dynamic proxy — cglib now uses more is javasist to generate dynamic proxy. Baidu javasist

The abstract and real characters are the same as before!

4.1 rent.java is an abstract role

Public interface Rent {public void Rent (); }Copy the code

4.2 host. Java is a real role

Public class Host implements Rent{public void Rent () {system.out.println (" implements Rent "); }}Copy the code

4.3 proxyInvocationHandler. Java is the proxy role

public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent) { this.rent = rent; } // Generate the proxy class, focusing on the second argument, to get the abstract role to proxy! It was all one character before, Public Object getProxy(){return proxy.newProxyInstance (this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } // proxy: method: @override public Object invoke(Object proxy, Method Method, Object[] args) throws Throwable { seeHouse(); // Core: Essence is realized by reflection! Object result = method.invoke(rent, args); fare(); return result; } public void seeHouse(){system.out.println (); } public void fare(){system.out.println (" out.println "); }}Copy the code

4.4 Client. Java

Public class Client {public static void main(String[] args) {// Real role Host Host = new Host(); Pih = new ProxyInvocationHandler(); pih = new ProxyInvocationHandler(); pih.setRent(host); // Put the real character in! Rent proxy = (Rent)pih.getProxy(); // Dynamically generate the corresponding proxy class! proxy.rent(); }}Copy the code

5. Deepen understanding

Let’s implement the proxy using the dynamic proxy we’ll write later UserService! We could also write a generic dynamic proxy implementation class! Set all proxy objects to Object!

public class ProxyInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; Public Object getProxy(){return proxy.newproxyInstance (this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } // method: Public Object invoke(Object proxy, Method Method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String methodName){system.out.println (" execute "+ "method "); }} public class Test {public static void main(String[] args) {UserServiceImpl userService = new UserServiceImpl(); Pih = new ProxyInvocationHandler(); pih = new ProxyInvocationHandler(); pih.setTarget(userService); // Set the object to proxy UserService proxy = (UserService)pih.getProxy(); // Dynamically generate proxy classes! proxy.delete(); }}Copy the code

6. Test dynamic proxy:

/** * @description test dynamic proxy * @author: zhangh * @date: 2020/11/30 11:18 */ public class Test { public static void main(String[] args) { UserService userService = new UserServiceImpl(); ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(); proxyInvocationHandler.setObject(userService); / / only interface UserService proxy = (UserService) proxyInvocationHandler. GetProxy (); proxy.add(); }}Copy the code

The results are as follows:

7,

The biggest advantage of dynamic proxies compared to static proxies is that all methods declared in the interface are moved to a centralized method of the calling handler (InvocationHandler.invoke). In this way, when the number of interface methods is large, we can do flexible processing without the need for each method to be mediated like a static proxy. And the application of dynamic proxy makes our class responsibility more simple, more reusable.