Implementation of dynamic proxy in java

  • 2020-05-27 04:47:16
  • OfStack

Implementation of dynamic proxy

Pattern used: proxy pattern.

The proxy pattern provides a proxy for other objects to control access to this object. Sort of a rental agent.

Two dynamic proxies:

(1) jdk dynamic proxy, jdk dynamic proxy is implemented by the internal reflection mechanism of Java, and the target class is based on the unified 1 interface (InvocationHandler).

(2) cglib dynamic proxy, cglib dynamic proxy is realized by asm at the bottom, and cglib dynamic proxy realized by the third party library is more widely used and has more advantages in efficiency.

Main application frameworks:

AOP in Spring, interceptors in Struts2

Specific implementation:

1. Define interfaces and implementation 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 it 1 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 1 A defect, cglib Make up for it 1 defects )
  }
  @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;

/**
 *  The 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));
  }
}

Operation results:

------before getName------
------getName------
------after getName------
cat
------getAge------
10

3. cglib dynamic agent implementation:

JDK dynamic proxy mechanism can only agent class implements an interface, and can't implement the interface class cannot be achieved JDK dynamic proxy, cglib is for class to implement proxy, his principle is to specify the target class to generate a subclass, and override the method, but because the inheritance, so can't class of final modification agent.

Core classes of CGLIB:

net. sf. cglib. proxy. Enhancer � major enhancement class
net. sf. cglib. proxy. MethodInterceptor � major methods to intercept, it is Callback interface sub interface, users need
net. sf. cglib. proxy. MethodProxy � JDK java. lang. reflect. Method agent, can easily realize the source object method invocation.

net. sf. cglib. proxy. MethodInterceptor interface is the most common type of callback (callback), it is often based on the agent's AOP used to implement interception (intercept) method is called. This interface defines only one method
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;

The first parameter is the proxy image, 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.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 a proxy object 
   *
   * @param target
   * @return
   */
  public Object getInstance(Object target) {
    this.target = target;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(this.target.getClass());
    //  The callback method 
    enhancer.setCallback(this);
    //  Create a 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);
  }
}

Operation results:

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


Related articles: