Proxy Mode Is Enough to Read This Article

Proxy mode is enough to read this article Solution


Foreword
Proxy mode. I wonder if you still remember these two articles: APP startup process analysis and Android Hook telling you how to start an unregistered Activity. The technical basis used in these two articles includes the proxy mode, which also said in the article "When it comes to the proxy In fact, it is the proxy mode, you can continue to follow me about what the proxy mode is and the use of dynamic and static proxies, and I will write a separate article to introduce it later.”
Now a whole year has passed, and I am still the boy I used to be, and I have not changed in the slightest. Here comes this article~

Proxy mode.What is proxy mode


Proxy mode. When it comes to design patterns, we are very far away and very close.
Ask many engineers what design patterns have been used, and I believe many people will say singleton pattern , factory pattern, etc., but few people have mentioned bridge pattern, facade pattern, interpreter pattern, etc. and have never even heard of it.

Proxy mode.the proxy pattern is one of the structural patterns, which mainly combines classes and objects to solve specific application scenarios. For Android engineers, I think it is necessary to understand and master the proxy mode, because understanding plug-in technologies such as Android Hook and AMS proxy is inseparable from the proxy mode, which is why I always feel that there is this article, If you don't know what the proxy mode is for Android developers, move on to the two articles in the preface.
Use proxy mode

Proxy mode.The proxy mode simply means that the function can be extended by introducing the proxy class without changing the code of the proxy class. For example, we now have a login registration class LoginAndRegist.java and a login method and a registration method.
public void login( String userName ){
System.out.println ("I am the login method");
}
public void retain ( String userName ){
System.out.println ("I am the registration method");

At the same time, we create a new Test class to test the method
public class Test {
public static void main( String[] args ) {
LoginAndRegist loginAndRegist = new LoginAndRegist ( );
loginAndRegist.reist (" huanglinqing ");
loginAndRegist.login (" huanglinqing ");
}
}

Running Test.main prints the following:
I am the registration method
I am the login method
Process finished with exit code 0

So we now have a need to add relevant logs for login and registration. How can we achieve this? You may say, isn't it simple, just add two lines of printing directly in the login and register methods?
It can be but as the system gets bigger you will get more and more pain
The first LoginAndRegist class is not written by you, do you want to let the person in charge modify their own code?
The second add log is a log system is an independent system and should not be mixed with business
Third, what if the class to add the log is in the jar package?
********
static proxy
So how do we implement the above functions? We take the login registration method to add a time log as an example. First of all, when an experienced engineer writes code, he should know that we have to follow the design principle based on interface rather than implementation, so we Login and register should be extracted, and the LoginAndRegist class should inherit the cover interface, as shown below:
public interface UserInter {
/**
* Log in
* @param name name
*/
void login( String name);
/**
* register

* @param name name
*/
void register ( String name);
}

public class LoginAndRegist implements UserInter {
private static final String TAG = "Login";
@Override
public void login( String userName ) {
System.out.println ("I am the login method");
}
@Override
public void register ( String name) {
System.out.println ("I am the registration method");
}
}

Create a proxy class LoginAndRegistProxy for the LoginAndRegist class , let the proxy class implement the same interface as the original class, call the method of the original class, and print the current timestamp before calling, the code is as follows:
public class LoginAndRegistProxy implements UserInter {
private static final String TAG = "Login";
private UserInter userInter ;
public LoginAndRegistProxy ( UserInter userInter ) {
this.userInter = userInter ;
}
@Override
public void login( String userName ) {
System.out.println ("The time of calling the login interface: " + System.currentTimeMillis ());
userInter.login ( userName );
}
@Override
public void register ( String name) {
System.out.println ("Time of calling registration interface: " + System.currentTimeMillis ());
userInter.login (name);
}
}

Modify the calling method in Test to call the proxy class:
public static void main( String[] args ) {
LoginAndRegist loginAndRegist = new LoginAndRegist ( );
LoginAndRegistProxy loginAndRegistProxy = new LoginAndRegistProxy ( loginAndRegist );
loginAndRegistProxy.regist (" huanglinqing ");
loginAndRegistProxy.login (" huanglinqing ");
}

Proxy mode.The execution result is as follows:


Time of calling the registration interface: 1596793891141
I am the login method
Time of calling the login interface: 1596793891141
I am the login method
Process finished with exit code 0

Proxy mode.In this way, we have realized the function of adding logs to the class method without changing the original. However, the problems of this method are also mentioned above.
First what if the original class does not implement the interface
Second, what if we can't get the source code of the original class
For the case where the original class does not implement the interface and we cannot modify it, this is called the extension of the external class. We generally use the inheritance method to extend the extension of the external class, and we will not explain this method.
Third, if you add a proxy class for each class , it will increase a lot of files
The third problem is the first problem we need to solve in actual development, so in order to solve the problem of too many static proxy files , we need to use dynamic proxy.

Proxy mode.Dynamic proxy


Proxy mode.Dynamic proxy simply means that we do not need to write a proxy class for an original class in advance, but dynamically create a proxy class at runtime, and then replace the original class with a proxy class. The charm of dynamic proxies is really very, very big in Android. If you don't know it yet, be sure to look back at the two articles mentioned in my preface. The foundation of dynamic proxy in java is reflection. If you don't know reflection technology, please move to my article Java reflection technology detailed
dynamic proxy, we mainly rely on the newProxyInstance method, which returns an instance of the specified interface proxy class.
public static Object newProxyInstance ( ClassLoader loader,
Class[ ] interfaces, InvocationHandler h)

The first parameter loader refers to the classLoader corresponding to the target object class
The second parameter, interfaces, is set to the interface type implemented by the object class. The first parameter and the second parameter are actually fixed in business. Here are the classLoader and interface type corresponding to UserInter .
We mainly look at the third parameter InvocationHandler , which is a class object that implements the InvocationHandler interface
First let's define a MyInvocationHandler to implement InvocationHandler
public class MyInvocationHandler implements java.lang .reflect.InvocationHandler {
@Override
public Object invoke( Object proxy, Method method , Object[] args ) throws Throwable {
return null;
}
}

The invoke method implemented here is the core of the dynamic proxy. In addition, we need to pass in the proxy class and execute the proxy method in the invoke method.
public class MyInvocationHandler implements java.lang .reflect.InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始执行前:" + method.getName());
Object object = method.invoke(target, args);
System.out.println ("End of execution:" + method.getName ());
return object;
}
}

method.invoke method in invoke . args are the parameters required to execute the corresponding method. We add logs before and after the method.
As we have said above, the dynamic proxy is created by the newProxyInstance method, let's see how to use it in Test
public static void main( String[] args ) {
UserInter loginAndRegist = new LoginAndRegist();
UserInter loginAndRegistProxy = (UserInter) Proxy.newProxyInstance(loginAndRegist.getClass().getClassLoader(),
loginAndRegist.getClass().getInterfaces(),new MyInvocationHandler(loginAndRegist));
loginAndRegistProxy.regist("huang_动态代理");
loginAndRegistProxy.login (" huang_static proxy");
}

newProxyInstance have been explained above, and the running result is as follows:
Before starting execution: regist
I am the registration method
End of execution: register
Before starting execution: login
I am the login method
End of execution: login
Process finished with exit code 0

In this way, we add logs to the methods of all classes uniformly through dynamic proxy.
In Android, we use the object generated by Proxy.newProxyInstance to directly replace the original object. This technology is the Hook technology that sounds very high.
In addition, the underlying implementation principle of Spring AOP is based on dynamic proxies.
What are the other application scenarios of the proxy mode?
If we want to apply the proxy mode well, we need to understand the application scenarios of the proxy mode
Business system non-functional requirements
Some non-functional requirements in the business system, such as monitoring, statistics, authentication, transactions, logs, etc. We decouple these additional functions from the business functions and put them into the proxy class for unified processing, so that we can decouple them from the business and achieve clear division of responsibilities.
widely used in RPC technology, Android Hook, plug-in and other technical fields.
Do you now have a clear understanding of the proxy pattern?

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00