What is AOP?
Many people on the web describe AOP as a technique for faceted programming that implements uniform maintenance of program functionality through precompilation and runtime dynamic proxies. Personally, I think this sentence is wrong. AOP, like OOP, is a programming idea, not a technical approach.
There are six principles of programming, the first of which is the single responsibility principle. This means that a class is responsible for only one thing. This works well with the encapsulation nature of OOP. Under this condition, our programs are divided into different classes and different methods. The benefits are reduced class complexity and increased program maintainability. But at the same time, it makes the code verbose. For example, if we wanted to add call logging for a method, we would have to add log calls for all methods of all classes, even though they are the same. In order to solve the above problems, AOP came into being.
AOP aims to improve the modularity of program code by classifying crosscutting concerns from business principals. Crosscutting concerns are an abstract concept that refers to businesses that span multiple modules in a project. The logging feature in the previous example is a typical crosscutting concern.
Several implementations of AOP
A dynamic proxy
Dynamic proxy is a design pattern. It has the following characteristics:
- We don’t need to write proxy classes ourselves.
- The runtime generates proxy objects directly through the interface.
- Which object is proxied is determined at run time.
Using the following example, let’s look at the class diagram structure of a dynamic proxy.
Usually, some functions of our APP require users to log in before they can access them. For example, you can change passwords and user names. When a user intends to use these functions, we generally need to judge the user’s login status. Only after the user logs in, can these functions be used normally. If the user does not log in, our APP will jump to the login page. Take changing passwords as an example and look at the class diagram of dynamic proxy.
InvocationHandler is a dynamic proxy entry provided by the Java JDK that handles methods on the propped object.
The code is as follows:
public static class LoginCheckHandler implements InvocationHandler {
private static <S, T extends S> T proxy(S source, Class<T> tClass) {
return (T) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[]{tClass}, new LoginCheckHandler(source));
}
private Object mSource;
LoginCheckHandler(Object source) {
this.mSource = source;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(! checkLogin()){ jumpToLoginActivity();return null;
}
return method.invoke(mSource, args);
}
private boolean checkLogin(a){
System.out.println("User not logged in");
return false;
}
private void jumpToLoginActivity(a){
System.out.println("Jump to login page"); }}public class Client {
public static void main(String[] args) {
IUserSetting source = new UserSetting();
IUserSetting iUserSetting = LoginCheckHandler.proxy(source,IUserSetting.class);
iUserSetting.changePwd("new Password"); }}Copy the code
With this encapsulation, the logic of checking login to jump to the login page is separated from the business body as a crosscutting concern. When there is a new requirement to log in to check, we simply generate a new proxy object through the LoginCheckHandler.
APT
APT(Annotation Processing Tool) is a compile-time Annotation Processing technology. It implements compile-time code generation by defining annotations and handlers, and compiles the generated code along with the source code into a.class file. We use APT technology to encapsulate crosscutting concerns into annotation processors, thus separating crosscutting concerns from business bodies. For a more detailed introduction, please move to Android compile time peg and let the program write its own code (a).
AspectJ
AspectJ is a compiler that adds keyword recognition and compilation methods to the Java compiler. As a result, AspectJ can compile Java code. It also provides Aspect programs. During compilation, the Aspect program written by the developer is woven into the target program to expand the function of the target program. Developers implement AOP functionality by writing AspectJ programs. For a more detailed introduction, please move to Android compile time staking and let the program write its own code (two).
Transform + Javassist/ASM
Transform is a way of manipulating bytecodes provided by Android Gradle. When the App is compiled, the source code is first compiled into class and then into dex. When a class is compiled into a dex, it goes through a series of transforms. Javassist/ASM is a very handy library for manipulating bytecodes. They allow us to modify compiled.class files. In this way, we encapsulate the crosscutting concern into a Transform to separate it from the business body. For a more detailed introduction, please move to Android compile time staking and let the program write its own code (three).
What can we do with it?
There are some interesting things you can do with AOP. Several well-known open source frameworks have adopted the idea of AOP. Examples: ButterKnife, Retrofit, Hugo, etc. In addition, AOP in performance detection and buried point technology appeared a hundred schools of contention situation.
- Performance testing and optimization. ArgusAPM for 360, booster for didi, and Hugo for Jake Wharton.
- Buried point technique. DDAutoTracker, Smart Data Sensors Analytics, netease HubbleData, etc.
In addition, with AOP we can implement the following functions:
-
Typically when we request data from the server, we display a Loding and hide it after the results are returned. We can use AOP techniques to separate the action of showing and hiding Loding from the business principals.
-
Permission management. I recommend Aopermission, an open source library that uses AspectJ to solve the permissions problem.