Proxy pattern: It is a design pattern that provides additional access to the target object, that is, access to the target object through the proxy object, so as to provide additional functional operations and expand the function of the target object without modifying the original target object.
In short: Enhance the code without modifying the source code
Static proxy
Write the static code directly, and you will understand it by reading the code.
public interface UserDao { public void save(); }
public class UserDaoImpl implements UserDao{ @Override public void save() { System.out.println("Save data"); } }
public class UserDaoProxy implements UserDao{ private UserDao userDao; public UserDaoProxy(UserDao userDao){ this.userDao = userDao; } @Override public void save() { System.out.println("Open a transaction"); userDao.save(); System.out.println("Transaction submission"); } }
public class Test { public static void main(String[] args) { UserDao userDao = new UserDaoProxy(new UserDaoImpl()); System.out.println(userDao.getClass()); userDao.save(); } }
test result
class com.UserDaoProxy Open a transaction Save data Transaction submission
It's easy to see its drawbacks from the above code:
1. Redundancy - Because the proxy object implements the same interface as the target object, it will produce too many proxy classes. 2. Not easy to maintain - once the interface is added, both the target object and the proxy object need to be modified.
Dynamic Agent
The main differences between static agent and dynamic agent are as follows:
1. Static proxy is implemented at compile time, and the proxy class after compilation is an actual class file. 2. Dynamic proxy is generated dynamically at runtime, that is, there is no actual class file after compilation, but class bytecode is generated dynamically at runtime and loaded into JVM.
Classification:
jdk dynamic proxy: an interface-based dynamic proxy (the proxy class implements at least one interface and cannot be used if not) CGLib proxy: dynamic proxy based on subclasses (proxy class cannot be final class)
Let's briefly talk about JDK dynamic proxy
Create proxy objects - - - using the new ProxyInstance method in the Proxy class
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
Introduction of the parameters of the new Proxy Instance method
ClassLoader: Class Loader - It is used to load the bytecode of the proxy object, and the proxy object uses the same class loader, fixed writing. Class [] bytecode array - It is used to make proxy objects and proxy objects have the same method, fixed writing Invocation Handler is used to provide enhanced code -- let's write how to proxy
Here's an example (proxy class or above)
public class DynStaticFactory { private Object target;// Maintaining a target object public DynStaticFactory(Object target) { this.target = target; } // Generate proxy objects for target objects public Object getProxyInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * Any interface method of the proxy object is executed through this method * @param proxy References to proxy objects * @param method Current method of execution * @param args The parameters needed to execute the current method * @return Have the same return value as the proxy object * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Open a transaction"); // Executing target object method Object returnValue = method.invoke(target, args); System.out.println("Submission transaction"); return null; } }); } } ```java public class TestDyn { public static void main(String[] args) { DynStaticFactory dynStaticFactory = new DynStaticFactory(new UserDaoImpl()); UserDao userDao = (UserDao)dynStaticFactory.getProxyInstance(); System.out.println(userDao.getClass()); userDao.save(); } }
test result
class com.sun.proxy.$Proxy0 Open a transaction Save data Submission transaction