In some Java projects, MapperScannerConfigurer is used in the integration of mybatis and spring. This class automatically generates interface-based dynamic proxy classes through reverse proxy.
In view of this, this article briefly analyzes Java's dynamic proxy.
This article uses a dynamic proxy to simulate an interceptor that handles transactions.
interface:
public interface UserService { public void addUser(); public void removeUser(); public void searchUser();}Implementation class:
public class UserServiceImpl implements UserService { public void addUser() { System.out.println("add user"); } public void removeUser() { System.out.println("remove user"); } public void searchUser() { System.out.println("search user"); }}There are two ways to implement java dynamic proxy
1. The dynamic proxy that comes with jdk
To use the dynamic proxy that comes with jdk, you need to understand the InvocationHandler interface and Proxy class. They are both under the java.lang.reflect package.
InvocationHandler introduction:
InvocationHandler is the interface implemented by the invocation handler of the proxy instance.
Each proxy instance has an associated InvocationHandler. When calling a method on a proxy instance, this method calls the invoke method of the InvocationHandler.
Proxy introduction:
Proxy provides static methods for creating dynamic proxy classes and instances.
Example (simulating AOP transaction processing):
public class TransactionInterceptor implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println ("start Transaction"); method.invoke(target, args); System.out.println("end Transaction"); return null; }}Test code:
public class TestDynamicProxy { @Test public void testJDK() { TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); UserService userService = new UserServiceImpl(); transactionInterceptor.setTarget(userService); UserService userServiceProxy = (UserService) Proxy.newProxyInstance( userService.getClass() .getClassLoader(), userService.getClass().getInterfaces(), transactionInterceptor); userServiceProxy.addUser(); }}Test results:
start Transactionadd userend Transaction
Obviously, when we make a method call through the userServiceProxy proxy class, the transaction will be opened and closed before and after the method call.
2. Third-party library cglib
CGLIB is a powerful, high-performance, high-quality code generation library for extending Java classes and implementing Java interfaces at runtime.
The biggest difference between it and JDK's dynamic proxy is:
JDK dynamic proxy is for interfaces, while cglib implements proxy for classes. The principle of cglib is to generate a subclass for the specified target class and overwrite the methods to achieve enhancement. However, because inheritance is used, final cannot be The modified class is proxied.
The example code is as follows:
public class UserServiceCallBack implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("start Transaction by cglib"); methodProxy.invokeSuper(o, args ); System.out.println("end Transaction by cglib"); return null; }}Test code:
public class TestDynamicProxy { @Test public void testCGLIB() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserServiceCallBack()); UserServiceImpl proxy = (UserServiceImpl)enhancer.create() ; proxy.addUser(); }}Test results:
start Transaction by cglibadd userend Transaction by cglib
Interested readers can actually test the examples in this article, and I believe they will gain a lot.