English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Deep Understanding of Java Dynamic Proxy Mechanism

Retrofit is a highly decoupled network request framework, and during recent research, I discovered a very powerful and practical technology called dynamic proxy. This article will serve as a prerequisite for Retrofit, helping everyone understand: What are the application scenarios of dynamic proxy, what is dynamic proxy, how to use it, and where are its limitations?

Application scenarios of dynamic proxy

1. AOP—Aspect-Oriented Programming, program decoupling

In short, when you want to perform some common operations before and after the execution of some internal methods of certain classes, while executing personalized operations in the methods--Use dynamic proxy. It can reduce the amount of code and enhance maintainability when there is a large amount of business.

2. Want to customize certain methods of a third-party library

I have referenced a third-party library, but some of its methods do not meet my needs, and I want to rewrite those methods myself or add some special operations before and after the methods--Use dynamic proxy. But it should be noted that these methods have limitations, and I will explain later.

What is dynamic proxy

The above diagram is too abstract, let's start with a real-life example.

Suppose you are a landlord (principal), you have many houses to rent out, and you find it麻烦 to find tenants and are unwilling to do it yourself, so you find someone to act as your agent (agent) to help manage these things, and this person (agent, also known as the intermediary) charges you some intermediary fees (additional operations for house rental) when helping you rent out the house. For tenants, the intermediary is the landlord, acting on your behalf.

In summary, this is an example of an agent, and why it is called "dynamic proxy", where do the words "dynamic" manifest?

We can think like this, if you hire an agent for each of your houses, every time you want to rent out a new house, you have to hire another one, so you will hire many agents, incurring high intermediary costs, which can be regarded as the commonly said "static proxy".

But if we entrust all the houses to an agency to act as an intermediary, allowing it to switch identities dynamically between multiple houses, helping you deal with each tenant. This is a process of "dynamic proxy". One of the major characteristics of dynamic proxy is that there is no proxy class at the compilation stage, and the proxy class is generated at runtime.

Let's take a look at a piece of code to understand

House rental operations

/**
*Define an interface
**/
public interface RentHouse {
void rent();//House rental
void charge(String str);//House rental charge collection
}

Landlord

public class HouseOwner implements RentHouse {
public void rent() {
  System.out.println("I want to rent my house");
}
public void charge(String str) {
  System.out.println("You get : ") + str + "RMB House Charge.");
}
}

Intermediary

public class DynamicProxy implements InvocationHandler {
// This is the real object we want to proxy, that is, the landlord
private Object subject;
// Constructor method, assign the initial value to the real object we want to proxy
public DynamicProxy(Object subject) {
  this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  //  We can add some of our own operations before proxying the real object, and the intermediary charges an intermediary fee
  System.out.println("before ",+method.getName()+" house");
  System.out.println("Method:") + method.getName());
  //    If the method is charge, the intermediary charges100 Yuan intermediary fee.
  if (method.getName().equals("charge")) {
    method.invoke(subject, args);
    System.out.println("I will get 100 RMB ProxyCharge.")
  } else {
    //  When the proxy object calls the method of the real object, it will automatically jump to the invoke method of the associated handler object of the proxy object for the call
    method.invoke(subject, args);
  }
  //  We can also add some of our own operations after proxying the real object
  System.out.println("after ",+method.getName()+" house");
  return null;
}
}

Guest

public class Client {
public static void main(String[] args)
{
  //  The real object we want to proxy--Landlord
  HouseOwner houseOwner = new HouseOwner();
  //  We pass in the real object we want to proxy, and finally, it is through the real object that we call its methods
  InvocationHandler handler = new DynamicProxy(houseOwner);
  /*
   * We create our proxy object through the newProxyInstance method of Proxy, let's take a look at its three parameters
   * The first parameter handler.getClass().getClassLoader(), here we use the ClassLoader object of the handler class to load our proxy object
   * The second parameter realSubject.getClass().getInterfaces(), here we provide the interfaces for the proxy object that the real object implements, indicating that I want to proxy this real object, so that I can call the methods in this set of interfaces
   * The third parameter handler, here we associate this proxy object with the above InvocationHandler object
   */
  RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner
      .getClass().getInterfaces(), handler);//A dynamic proxy class, the intermediary
  System.out.println(rentHouse.getClass().getName());
  rentHouse.rent();
  rentHouse.charge("10000");
}
}

Let's take a look at the output

com.sun.proxy.$Proxy0
before rent house
Method:rent
I want to rent my house
after rent house
before charge house
Method:charge
You get : 10000 RMB HouseCharge.
I will get 100 RMB ProxyCharge.
after charge house
Process finished with exit code 0

The output contains 'before rent house' and 'after rent house', indicating that we can add operations before and after the method. Moreover, looking at the output 'I will get 100 RMB ProxyCharge. The intermediary has collected10No intermediary fee of 0 RMB indicates that we can not only add operations but also replace the method or even make the method not execute directly.

At the beginning, when you look at the code, you may have many doubts. Let's take a look at how to use dynamic proxy through the following content.

How to use dynamic proxy

In Java's dynamic proxy mechanism, there are two important classes and interfaces: one is InvocationHandler (Interface), and the other is Proxy (Class). These classes and interfaces are necessary for implementing our dynamic proxy.

Every dynamic proxy class must implement the InvocationHandler interface (the intermediary in the code), and each instance of the proxy class is associated with a handler. When we call a method through the proxy object, the method call is forwarded to the invoke method of the InvocationHandler interface (where the enhancement of the method is written).

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

We see that this method takes three parameters in total. Then, what do these three parameters represent?

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
//proxy: It represents the real object that we are proxying
//method: It represents the Method object of the method we want to call on the real object
//args: It represents the parameters accepted when calling a method of the real object

Next, let's take a look at the Proxy class

public static Object newProxyInstance(ClassLoader loader, Class<63;][

The Proxy class is used to dynamically create a proxy object. It provides many methods, but the most commonly used one is newProxyInstance method:

public static Object newProxyInstance(ClassLoader loader, Class<63;][

The role of this method is to obtain a dynamic proxy object, which accepts three parameters. Let's take a look at the meanings of these three parameters

public static Object newProxyInstance(ClassLoader loader, Class<63;][
//loader: A ClassLoader object that defines which ClassLoader object will load the generated proxy object
//interfaces: An array of Interface objects, representing the set of interfaces that I will provide to the objects that need to be proxied. If I provide a set of interfaces to it, then the proxy object claims to implement the interface (polymorphism), so that I can call the methods in the set of interfaces.
//h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

h: An InvocationHandler object, which represents that when this dynamic proxy object calls a method, it will be associated with which InvocationHandler object

In this way, combined with the code given above, we can understand the usage method of dynamic proxy

Limitations of dynamic proxy
As we can see from the usage method of dynamic proxy, the methods that can be enhanced are all implemented by interfaces (public methods that do not implement interfaces can also be used by inheriting the proxy class), and the code in the HouseOwner class inherits RentHouse. However, the dynamic proxy of JDK is helpless for private methods!

Conclusion

The use scenarios of dynamic proxy are not limited to these, the internal principles will be introduced in future articles, but the mechanism of application class reflection temporary generation proxy class determines that it will have a certain impact on performance. This article as a preliminary article for retrofit principle is not very detailed, and welcome to correct any omissions and errors!

That's all for this article. I hope it will be helpful to everyone's study and that everyone will support the Yelling Tutorial more.

Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously, and this website does not own the copyright. It has not been manually edited and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please report via email to codebox.com (replace # with @ when sending an email) and provide relevant evidence. Once verified, this site will immediately delete the infringing content.

You May Also Like