java design pattern - proxy pattern

What is the proxy model

By controlling the access of an object through a proxy, you can access the method of an object in detail, and process it when the method is called or after the call. Existing (AOP micro Implementation)   , AOP core technology is aspect oriented programming.

Proxy mode application scenario  

Spring AOP, transaction principle, log printing, permission control, remote call and security agent can hide the real role

Classification of agents

Static proxy (statically defined proxy class), dynamic proxy (dynamically generated proxy class), Jdk's own dynamic proxy, Cglib, javaassist (bytecode operation Library)

  Static proxy

What is a static proxy?

The programmer creates or tool generates the source code of the agent class, and then compiles the agent class. The so-called static means that the bytecode file of the agent class already exists before the program runs, and the relationship between the agent class and the delegate class is determined before the program runs.

public interface IUserDao {
	void save();
}
public class UserDaoImpl implements IUserDao {
	public void save() {
		System.out.println("Data saved...");
	}
}
//proxy class
public class UserDaoProxy implements IUserDao {
	private IUserDao target;

	public UserDaoProxy(IUserDao iuserDao) {
		this.target = iuserDao;
	}

	public void save() {
		System.out.println("Open things...");
		target.save();
		System.out.println("Close things...");
	}

}
public class Test {
	public static void main(String[] args) {
		IUserDao userDao = new UserDaoImpl();
        UserDaoProxy userDaoProxy = UserDaoProxy(userDao);
        userDaoProxy.save();
	}

}

Dynamic agent

What is a dynamic proxy

1. The proxy object does not need to implement the interface

2. The generation of proxy object is to dynamically build proxy object in memory by using JDK API (we need to specify the type of interface to create proxy object / target object)

3. Dynamic agent is also called JDK agent and interface agent

JDK dynamic agent

1) Principle: create a proxy class according to the class loader and interface (this proxy class is the implementation class of the interface, so you must use the interface to generate an interface oriented proxy, which is located under the java.lang.reflect package)

2) Implementation method:

1. Create your own calling processor by implementing the InvocationHandler interface. InvocationHandler handler = new invocationhandlerimpl (...);

2. Create a dynamic Proxy class Class clazz = Proxy.getProxyClass(classLoader,new Class [] {...}) by specifying a ClassLoader object and a set of interface s for the Proxy class;

3. Obtain the constructor of the dynamic proxy class through the reflection mechanism. Its parameter type is the calling processor interface type Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});

4. Create a proxy class instance through the constructor. At this time, the calling processor object needs to be passed into Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler)) as a parameter;

Disadvantages: jdk dynamic proxy must be interface oriented, and the target business class must implement the interface

// Each time the dynamic proxy class object is generated, the calling processor object of the InvocationHandler interface is implemented 
public class InvocationHandlerImpl implements InvocationHandler {
	private Object target;// This is actually a business implementation class object, which is used to call specific business methods
	// Pass in the target object through the constructor
	public InvocationHandlerImpl(Object target) {
		this.target = target;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		System.out.println("Call start processing");
		result = method.invoke(target, args);
		System.out.println("Call end processing");
		return result;
	}

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// Proxied object
		IUserDao userDao = new UserDao();
		InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao);
		ClassLoader loader = userDao.getClass().getClassLoader();
		Class<?>[] interfaces = userDao.getClass().getInterfaces();
		// The main loader, a set of interfaces and call processing dynamic proxy instances
		IUserDao newProxyInstance = (IUserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);
		newProxyInstance.save();
	}

}

CGLIB dynamic proxy

Principle: use asm open source package to load the class file of proxy object class and generate subclasses by modifying its bytecode.  

What is CGLIB dynamic proxy

Using cglib[Code Generation Library] to implement the dynamic proxy does not require the delegate class to implement the interface. The bottom layer uses asm bytecode generation framework to generate the bytecode of the proxy class

public class CglibProxy implements MethodInterceptor {
	private Object targetObject;
	// If the target type here is Object, you can accept any parameter as the proxied class to realize dynamic proxy
	public Object getInstance(Object target) {
		// Set the class that needs to be subclassed
		this.targetObject = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println("Open things");
		Object result = proxy.invoke(targetObject, args);
		System.out.println("Close things");
		// Return proxy object
		return result;
	}
	public static void main(String[] args) {
		CglibProxy cglibProxy = new CglibProxy();
		UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao());
		userDao.save();
	}
}

The difference between CGLIB dynamic proxy and JDK dynamic proxy

java dynamic proxy uses reflection mechanism to generate an anonymous class that implements the proxy interface. It calls InvokeHandler before calling the specific method.

cglib dynamic proxy uses asm open source package to load the class file of proxy object class and generate subclasses by modifying its bytecode.

In Spring.

1. If the target object implements the interface, the dynamic proxy of JDK will be used to implement AOP by default

2. If the target object implements an interface, you can force the use of CGLIB to implement AOP

3. If the target object does not implement the interface, the CGLIB library must be used, and spring will automatically convert between JDK dynamic agent and CGLIB

JDK dynamic proxy can only generate proxy for classes that implement interfaces, not for classes.
CGLIB implements a proxy for a class. It mainly generates a subclass of a specified class and overrides the methods in it.
Because it is inheritance, it is better not to declare this class or method as final. Final can prevent inheritance and polymorphism.

Tags: Java

Posted on Sat, 18 Sep 2021 11:34:57 -0400 by neogemima