The proxy pattern is a common design pattern in Java development. The purpose of the design is to insert other functions between the service class and the customer class. The inserted functions are transparent to the caller and act as camouflage control, such as the example tenant, agent, landlord. For the proxy mode, namely: client class, proxy class, delegate class (proxy class).

Two design principles for the proxy pattern:

1. Proxy classes and delegate classes have similar behavior (common)

2. Proxy classes enhance the behavior of the delegate class

How the proxy pattern is implemented

  • Static agent
  • A dynamic proxy

A case in field

Static agent

Provide a proxy for an object in a fixed role to control access to the object. Proxy classes and delegate classes have a common parent class and parent interface, so proxy objects can be used wherever delegate objects are used. The proxy class is responsible for pre-processing, filtering, dispatching requests to the delegate class for processing, and subsequent processing after the delegate class executes the request.

/** ** Interface abstract role * define behavior */
public interface Marry {
	public void toMarry(a);
}
Copy the code
/** * Target class real character */
public class You implements Marry{
    @Override
	public void toMarry(a) {
   		System.out.println("After all this time, when you... "); }}Copy the code
/** ** Agent Agent role * 1. Implements common interfaces with the target role * 2. Hold references to target classes * 3. Enhance target role behavior */
public class MarryCompany implements Marry{
	// Target role reference
	private Marry target;
	public MarryCompany(Marry target) {
		this.target = target;
	}
	public void before(a){
		System.out.println("Wedding scene tense arrangement......");
	}
	@Override
	public void toMarry(a) {
		before();
		target.toMarry();
		after();
	}
	public void after(a){
		System.out.println("Congratulations on entering the second phase of your life....."); }}Copy the code
public class Test {
    public static void main(String[] args) {
        // Construct the proxy role and pass in the real role
        MarryCompany marryCompany=new MarryCompany(newYou()); marryCompany.toMarry(); }}Copy the code

Static proxy has fixed roles for agents. For example, there are 20 DAO classes in the DAO layer. If the access permission of methods is to be proxy, 20 static proxy roles need to be created, which causes class explosion and cannot meet the needs of production.

A dynamic proxy

Compared with static proxy, dynamic proxy is more flexible in creating proxy objects. It will dynamically create proxy objects for the target object during the program run according to the needs of the reflection mechanism. Proxy behavior can be proxy for multiple methods, that is, to meet the needs of production and achieve the purpose of common code. Dynamic proxy can be implemented in two ways:

The JDK implements dynamic proxies

For the JDK dynamic proxy implementation is more complex, the callback method to realize the underlying principle of reference: rejoy.iteye.com/blog/162740…

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/** * JDK dynamic proxy */
public class JdkHandler implements InvocationHandler{
    / / the target class
    private Object target;
    public JdkHandler(Object target) {
   		this.target = target;
    }
    /** * Dynamically create proxy roles * while the program is running@return* /
    public Object getProxy(a){
    /** * get proxy object * 1. Class loader * 2. Array of interfaces implemented by target class * 3. The current class *@return* /
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        this);
	}
	public void before(a){
		System.out.println("Wedding scene tense arrangement......");
	}
	@Override//InvocationHandler internal parameter The method parameter of the current target class
	public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
		before();// Enhance real character behavior
        Object result= method.invoke(target, args);// Execute the real character method
		after();// Enhance real character behavior
		return result;
	}
	public void after(a){
		System.out.println("Congratulations on entering the second phase of your life....."); }}Copy the code

Cglib Dynamic Proxy Implementation (Understanding)

Code Generator library to manipulate bytecode. Different from the JDK, Proxy: a Proxy class must have an interface, which is fast to make and slow to execute. Cglib: Delegate class can have no interface, inheritance thinking to achieve similarity, making proxy process is slow, execution is fast. Mainly addresses proxy implementations without interface classes.

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>
Copy the code
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibInterceptor implements MethodInterceptor {
	private Object target;
	public CglibInterceptor(Object target) {
		this.target = target;
	}
	// Create proxy classes dynamically at runtime
	public Object getProxy(a){
        Enhancer enhancer=new Enhancer();
		// Set the parent class
		enhancer.setSuperclass(target.getClass());
        // Sets the class of the callback object that implements the interface
		enhancer.setCallback(this);
		return enhancer.create();
	}
	public void before(a){
		System.out.println("Wedding scene tense arrangement......");
	}
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2,MethodProxy arg3) throws Throwable {
		before();// Enhance real character behavior
		Object result= arg3.invoke(target, arg2);
		after();// Enhance real character behavior
		return result;
	}
	public void after(a){
		System.out.println("Congratulations on entering the second phase of your life....."); }}Copy the code

extension

Rules for UML representation

“Visibility” indicates whether the attribute is visible to elements outside the class, including Public, Private, Protected, and Friendly.

In the class diagram, they are represented by the symbols +, -, #, ~ respectively.

Class diagrams in UML have the following relationships:

Dependencies (dotted with arrows),

Association relation (solid line with X arrows),

Polymerization relation (solid line with hollow diamond),

Combinatorial relations (solid lines with solid diamonds),

Generalization relation (solid line with hollow triangular arrow),

Implementation relation (dotted line with hollow triangular arrow),

Where the coupling degree of generalization and implementation is equal, they are the strongest.