Summary of java dynamic proxy methods

  • 2020-06-19 10:10:58
  • OfStack

java dynamic proxy method summary

The interception capabilities of AOP are implemented by dynamic proxies in java. In plain English, this means adding section logic to the target class to generate an enhanced target class (which executes either before, after, or when the target class function throws an exception). Different cutting opportunities correspond to different types of Interceptor, such as BeforeAdviseInterceptor, AfterAdviseInterceptor and ThrowsAdviseInterceptor.

So how does the dynamic proxy implement the weaving of section logic (advise) into the target class method? Let's go into more detail and implement the two dynamic proxies used in AOP.

AOP source code using two kinds of dynamic proxy to achieve interception cutting function: jdk dynamic proxy and cglib dynamic proxy. Both methods exist at the same time, and each has its advantages and disadvantages. jdk dynamic proxy is implemented by the reflection mechanism inside Java, while cglib dynamic proxy is implemented by asm. In general, the reflection mechanism is more efficient during class generation, while asm is more efficient during related execution after class generation (you can solve the problem of inefficient asm class generation by caching the asm generated classes). It is also important to note that the jdk dynamic proxy must be based on the interface of the target class. Without the above premise, jdk dynamic proxy cannot be applied. It can be seen that jdk dynamic proxy has certain limitations. cglib, the third party library, is more widely used and has more advantages in efficiency.

1. Define interfaces and implementations


package com.meituan.hyt.test3.service; 
 
 
public interface UserService { 
  public String getName(int id); 
 
  public Integer getAge(int id); 
} 

package com.meituan.hyt.test3.service.impl; 
 
import com.meituan.hyt.test3.service.UserService; 
 
 
public class UserServiceImpl implements UserService { 
  @Override 
  public String getName(int id) { 
    System.out.println("------getName------"); 
    return "Tom"; 
  } 
 
  @Override 
  public Integer getAge(int id) { 
    System.out.println("------getAge------"); 
    return 10; 
  } 
} 

2. jdk dynamic proxy implementation


package com.meituan.hyt.test3.jdk; 
 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
 
 
public class MyInvocationHandler implements InvocationHandler { 
  private Object target; 
 
  MyInvocationHandler() { 
    super(); 
  } 
 
  MyInvocationHandler(Object target) { 
    super(); 
    this.target = target; 
  } 
 
  @Override 
  public Object invoke(Object o, 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.meituan.hyt.test3.jdk; 
 
import com.meituan.hyt.test3.service.UserService; 
import com.meituan.hyt.test3.service.impl.UserServiceImpl; 
 
import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Proxy; 
 
 
public class Main1 { 
  public static void main(String[] args) { 
    UserService userService = new UserServiceImpl(); 
    InvocationHandler invocationHandler = new MyInvocationHandler(userService); 
    UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), 
        userService.getClass().getInterfaces(), invocationHandler); 
    System.out.println(userServiceProxy.getName(1)); 
    System.out.println(userServiceProxy.getAge(1)); 
  } 
} 

The results


++++++before getName++++++
------getName------
++++++after getName++++++
Tom
------getAge------
10

3, cglib dynamic proxy implementation

Cglib is an excellent dynamic proxy framework. Its underlying layer USES ASM to dynamically generate subclasses of the proxy class in memory. CGLIB can implement dynamic proxy functions even if the proxy class does not implement any interfaces. CGLIB is simple to use and runs much faster than JDK's Proxy dynamic agent:

The core classes of CGLIB:


 net.sf.cglib.proxy.Enhancer  �   Major enhancement classes 
  net.sf.cglib.proxy.MethodInterceptor  �   The main method intercepts a class, and it is Callback A subinterface of an interface that requires user implementation 
  net.sf.cglib.proxy.MethodProxy  �  JDK the java.lang.reflect.Method Class to facilitate the implementation of the source object method calls , Such as: 
  Object o = methodProxy.invokeSuper(proxy, args);// Although the first 1 The parameter is the proxy object, also does not appear the problem of endless loop. 

net.sf.cglib.proxy.MethodInterceptor Interfaces are the most common callbacks ( callback ), which is often proxy-based AOP Used to implement interception ( intercept ) method. This interface is just defined 1 A method of 
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 intercepting method and method parameters, respectively. The original method may be through the use of java. lang. reflect. Reflection calls Method 1 of an object, or use net. sf. cglib. proxy. MethodProxy object invocation. net. sf. cglib. proxy. MethodProxy is usually preferred to use, because it's faster.


package com.meituan.hyt.test3.cglib; 
 
 
import net.sf.cglib.proxy.MethodInterceptor; 
import net.sf.cglib.proxy.MethodProxy; 
 
import java.lang.reflect.Method; 
 
 
public class CglibProxy implements MethodInterceptor { 
  @Override 
  public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { 
    System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); 
    System.out.println(method.getName()); 
    Object o1 = methodProxy.invokeSuper(o, args); 
    System.out.println("++++++before " + methodProxy.getSuperName() + "++++++"); 
    return o1; 
  } 
} 




package com.meituan.hyt.test3.cglib; 
 
import com.meituan.hyt.test3.service.UserService; 
import com.meituan.hyt.test3.service.impl.UserServiceImpl; 
import net.sf.cglib.proxy.Enhancer; 
 
 
 
public class Main2 { 
  public static void main(String[] args) { 
    CglibProxy cglibProxy = new CglibProxy(); 
 
    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(UserServiceImpl.class); 
    enhancer.setCallback(cglibProxy); 
 
    UserService o = (UserService)enhancer.create(); 
    o.getName(1); 
    o.getAge(1); 
  } 
} 

Operation results:


++++++before CGLIB$getName$0++++++
getName
------getName------
++++++before CGLIB$getName$0++++++
++++++before CGLIB$getAge$1++++++
getAge
------getAge------
++++++before CGLIB$getAge$1++++++

Thank you for reading, I hope to help you, thank you for your support to this site!


Related articles: