Proxy pattern is one of the common design patterns in Java. The so-called proxy mode means that the client does not directly call the actual object, but indirectly calls the actual object by calling the proxy.
Why call objects in this indirect form? Generally, because the client does not want to access the actual object directly, or because it is difficult to access the actual object, it can complete indirect access through a proxy object.
In real life, this kind of situation is very common, such as inviting a lawyer to act for a lawsuit.
The code for the following example is accessible Source code . Welcome to star, welcome to fork
UML diagrams of proxy patterns
From the UML diagram, we can see that both the proxy class and the real implemented class inherit the abstract subject class. The advantage of this is that the proxy class can have the same method as the actual class, which can ensure the transparency of the client's use.
Implementation of Agent Model
The proxy pattern can be implemented in two ways, one is static proxy class, the other is dynamic proxy which every framework likes. Next, let's talk about these two agent models.
Static proxy
Let's first look at the example of UML implementation above, and then at the characteristics of static proxies.
Implementation of Subject Interface
public interface Subject { void visit(); }
Two classes of Subject interface are implemented:
public class RealSubject implements Subject { private String name = "byhieg"; @Override public void visit() { System.out.println(name); } }
public class ProxySubject implements Subject{ private Subject subject; public ProxySubject(Subject subject) { this.subject = subject; } @Override public void visit() { subject.visit(); } }
Specific calls are as follows:
public class Client { public static void main(String[] args) { ProxySubject subject = new ProxySubject(new RealSubject()); subject.visit(); } }
Through the above proxy code, we can see the characteristics of the proxy mode. The proxy class accepts an object of Subject interface. Any object that implements the interface can be proxyed through the proxy class, which increases the generality. However, there are also drawbacks. Each proxy class must implement the interface of the delegate class (that is, realsubject) once. If the interface adds methods, the proxy class must also be modified. Secondly, each interface object of the proxy class corresponds to a delegate object. If there are many delegates, the static proxy class is very bulky and incompetent.
Dynamic proxy
Dynamic proxy is different from static proxy. It creates proxy class dynamically according to the object of proxy. In this way, we can avoid the problem of too many proxy class interfaces in static proxy. Dynamic proxy is implemented by reflection. It is generated by fixed rules with the help of Java's own java.lang.reflect.Proxy.
The steps are as follows:
- Write an interface for a delegate class, the Subject interface of a static proxy
- Implementing a real delegate class, the RealSubject class
- Create a dynamic proxy class, implement the InvocationHandler interface, and override the invoke method
- In the test class, the dynamic proxy object is generated.
The first two steps are the same as static proxy, but that's all. Step three, the code is as follows:
public class DynamicProxy implements InvocationHandler { private Object object; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(object, args); return result; } }
Step 4: Create dynamic proxy objects
Subject realSubject = new RealSubject(); DynamicProxy proxy = new DynamicProxy(realSubject); ClassLoader classLoader = realSubject.getClass().getClassLoader(); Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy); subject.visit();
Creating dynamic proxy objects requires the help of Proxy.newProxyInstance. The three parameters of the method are:
- ClassLoader loader represents the currently used appClassloader.
- Class <?>[] interfaces represent a set of interfaces implemented by the target object.
- InvocationHandler h represents the current instance object of the InvocationHandler implementation.
This is where we introduce the use of dynamic proxies. The realization of dynamic proxy, the realization of dynamic proxy with the help of non-JDK libraries, and their advantages and disadvantages will be introduced later.