SoFunction
Updated on 2025-03-08

Java two ways to implement dynamic proxy

1. JDK dynamic proxy

Java has its own proxy support in the package. This class () is used to dynamically generate proxy classes. You only need to pass in the target interface, the class loader of the target interface and the InvocationHandler to generate proxy classes and proxy objects for the target interface. We call this Java technology: Dynamic proxy

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
                   Class<?>[] interfaces,
                   InvocationHandler h)
  throws IllegalArgumentException
{
//...
}

It is stipulated in Java that in order to generate an object's proxy object, the object must have an interface, so interfaces must be an interface.

In dynamic proxy technology, no matter what method the user calls the proxy object, the invoke method of the InvocationHandler written by the developer is called (this is equivalent to the method call of the invoke method intercepting the proxy object).

Therefore, the overall process of JDK dynamic proxy is:

  1. Implement InvocationHandler, used to handle the logic after object intercepting. (The object must be an interface, or the parent class is an interface)
  2. Use to generate proxy objects.

The following is a specific example of implementing AOP using JDK dynamic code:

1. Target class

public interface UserService {
  void eat();
}
public class UserServiceImpl implements UserService {
  @Override
  public void eat() {
    ("Eat");
  }
}

2.Aspect class

public class MyAspect {
  /**
    * Pre-Notice
    */
  public void before() {
    ("Wash your hands first");
  }
}

3. Weaving process

/**
  * Factory class that generates proxy objects
  */
public class MyFactoryBean {

  private MyFactoryBean() {
  }
  
  public static UserService getInstance() {
    // target: target class    final UserService userService = new UserServiceImpl();
    // Aspect: Face-cut    final MyAspect myAspect = new MyAspect();
    // Weaving: Weaving, that is, the process of generating agents    UserService proxyInstance = (UserService) ((),
        new Class[]{}, (Object proxy, Method method, Object[] args) -&gt; {
          // Simulated point cut - pointcut          if ("eat".equals(())) {
            ();
          }
          return (userService, args);
        });
    return proxyInstance;
  }
}
  public static void main(String[] args) {
    UserService userService = ();
    // Wash your hands before eating    ();
  }

Think about it, this is actually very similar to the AOP we usually use. Spring defines pre-notifications (@Before), exception notifications (@AfterThrowing), etc. Spring just uses these annotations to select when to call the notification method. In addition, Spring also selects the target class and entry point through point-cut expressions.

2. CGLIB dynamic proxy

CGLIB dynamic proxy needs to introduce third-party libraries, which realize call interception by modifying the way the proxy object generates subclasses. The proxy object does not need to implement an interface, but the proxy class cannot be final, and the proxy method cannot be final.

/**
  * Factory class that generates proxy objects
  */
public class MyFactoryBean {

  private MyFactoryBean() {
  }

  public static UserService getInstance() {
    // target: target class    final UserService userService = new UserServiceImpl();
    // Aspect: Face-cut    final MyAspect myAspect = new MyAspect();
    // Weaving: Weaving, that is, the process of generating agents    Enhancer enhancer = new Enhancer();
    (());
    (false);
    (new MethodInterceptor() {
      @Override
      public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // Simulation pointcut-point cut        if ("eat".equals(())) {
          ();
        }
        return (o, objects);
      }
    });
    return (UserService) ();
  }

  public static void main(String[] args) {
    UserService proxyInstance = ();
    // Wash your hands before eating    ();
  }
}

3. Summary

When implementing dynamic proxy in JDK, it is required that the proxy class must be an interface or an inherited interface class, because the proxy class generated by the JDK actually implements the interface proxy by the proxy class and inherits the Proxy class in java (inheriting the Proxy class is to determine whether the class is a proxy class), finds the interface method through reflection, and calls the invoke method of the InvocationHandler to achieve interception.

CGLIB bytecode enhancement is a good complement to JDK dynamic proxy. The last generated proxy class in CGLIB is a class that inherits the proxy class, and implements the proxy by rewriting the non-final method in the proxy class.

Summary as:

  • JDK Dynamic Proxy: The proxy class must be an interface or a class that inherits the interface.
  • CGLIB bytecode enhancement: The proxy class cannot be final, and the proxy method cannot be final (inheritance limit).

Regarding what proxy methods are used in Spring's AOP, if we do not impose restrictions, we will treat them differently based on whether the class has an interface:

  1. When a class has an interface, it will use JDK dynamic proxy.
  2. When a class does not implement an interface, it will use the CGLIB proxy method.

The above is the detailed content of implementing dynamic proxy in two ways of Java. For more information about Java dynamic proxy, please follow my other related articles!