Implementation of dynamic proxy
Mode used: proxy mode.
The function of the proxy mode is to provide a proxy for other objects to control access to this object. Similar to a rental agency.
Two dynamic proxy:
(1) jdk dynamic proxy. jdk dynamic proxy is implemented by the reflection mechanism inside Java. The target class is based on a unified interface (InvocationHandler)
(2) Cglib dynamic proxy, and the underlying layer of cglib dynamic proxy is implemented with the help of asm. The dynamic proxy implemented by third-party library such as cglib is more widely used and has more advantages in efficiency.
Main application framework:
AOP in Spring, Interceptor in Struts2
Specific implementation:
1. Define interfaces and implement classes
package com.example.service;public interface UserService { public String getName(int id); public Integer getAge(int id);} package com.example.service.impl;import com.example.service.UserService;public class UserServiceImpl implements UserService { public String getName(int id) { System.out.println("------getName-----"); return "cat"; } public Integer getAge(int id) { System.out.println("------getAge-----"); return 10; }}2. jdk dynamic proxy implementation
package com.example.jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class MyInvocationHandler implements InvocationHandler { private Object target; /** * Bind the delegate object and return a proxy class* * @param target * @return */ public Object bind(Object target) { this.target = target; //Get the proxy object return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); //To bind the interface (this is a defect, cglib makes up for this defect) } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("getName".equals(method.getName())) { System.out.println("-------before " + method.getName() + "-----"); Object result = method.invoke(target, args); System.out.println("------after " + method.getName() + "------"); return result; } else { Object result = method.invoke(target, args); return result; } }} package com.example.jdk;import com.example.service.UserService;import com.example.service.impl.UserServiceImpl;/** * Test class*/public class RunJDK { public static void main(String[] args) { MyInvocationHandler proxy = new MyInvocationHandler(); UserService userServiceProxy = (UserService) proxy.bind(new UserServiceImpl()); System.out.println(userServiceProxy.getName(1)); System.out.println(userServiceProxy.getAge(1)); }}Running results:
------before getName----
------getName-----
------after getName-----
cat
-----getAge-----
10
3. CGlib dynamic proxy implementation:
JDK's dynamic proxy mechanism can only proxies the classes that implement interfaces, but classes that cannot implement interfaces cannot implement JDK's dynamic proxy. cglib implements proxy for classes. Its principle is to generate a subclass for the specified target class and overwrite the method implementation enhancement. However, because inheritance is used, the class modified by final cannot be proxyed.
Core classes of CGLIB:
net.sf.cglib.proxy.Enhancer Main enhancement class
net.sf.cglib.proxy.MethodInterceptor The main method intercepts the class, which is a subinterface of the Callback interface and requires user implementation.
net.sf.cglib.proxy.MethodProxy The proxy class of the java.lang.reflect.Method class of JDK can easily implement calls to source object methods.
The net.sf.cglib.proxy.MethodInterceptor interface is the most general callback type, and it is often used by proxy-based AOP to implement intercept method calls. This interface only defines one method
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;
The first parameter is the proxy object, and the second and third parameters are the intercepted method and the parameters of the method, respectively. The original method might be called by using a general reflection call using a java.lang.reflect.Method object, or by using a net.sf.cglib.proxy.MethodProxy object. net.sf.cglib.proxy.MethodProxy is usually preferred because it is faster.
package com.example.cglib;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CGLIBProxy implements MethodInterceptor { private Object target; /** * Create proxy object* * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // Callback method enhancer.setCallback(this); // Create proxy object return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("++++++++ before " + methodProxy.getSuperName() + "++++++"); System.out.println(method.getName()); Object result = methodProxy.invokeSuper(o, objects); System.out.println("++++++ after " + methodProxy.getSuperName() + "++++++++"); return result; }} package com.example.cglib;import com.example.service.UserService;import com.example.service.impl.UserServiceImpl;/** * Test CGLIB */public class RunCGLIB { public static void main(String[] args) { CGLIBProxy cglibProxy = new CGLIBProxy(); UserService userService = (UserService) cglibProxy.getInstance(new UserServiceImpl()); userService.getName(1); userService.getAge(1); }}Running results:
++++++ before CGLIB$getName$0++++++++
getName
------getName-----
++++++ after CGLIB$getName$0++++++++
++++++ before CGLIB$getAge$1++++++++
getAge
-----getAge-----
++++++ after CGLIB$getAge$1++++++++
The above is all the content of this article. I hope that the content of this article will be of some help to everyone’s study or work. I also hope to support Wulin.com more!