AOP (Aspect Orient Programming), as a supplement to object-oriented programming, is widely used to handle some system-level services with cross-cutting properties, such as transaction management, security checks, caching, object pool management, etc. The key to AOP implementation lies in the AOP proxy automatically created by the AOP framework. AOP proxies can be divided into two categories: static proxies and dynamic proxies. Static proxies refer to compilation using the commands provided by the AOP framework, so that they can be generated during the compilation phase. The AOP proxy class is also called compile-time enhancement; while the dynamic proxy uses JDK dynamic proxy, CGLIB, etc. to "temporarily" generate the AOP dynamic proxy class in the memory at runtime, so it is also called run-time enhancement.
The existence value of AOP
In traditional OOP programming, objects are the core. The entire software system is composed of a series of interdependent objects, and these objects will be abstracted into classes one by one. And allows the use of class inheritance to manage general to specific relationships between classes. As the scale of software increases and applications are gradually upgraded, some problems that are difficult to solve with OOP gradually appear.
We can analyze and abstract a series of objects with certain attributes and behaviors, and form a complete software function through collaboration between these objects. Since objects can be inherited, we can abstract attributes with the same functions or characteristics into a hierarchical class structure system. With the continuous expansion of software specifications, the increasing number of specialized divisions of labor, and the increasing number of OOP application practices, some problems that OOP cannot solve well have been exposed.
Now assume that there are 3 pieces of completely similar code in the system. These codes are usually completed using the "copy" and "paste" methods. The software developed through this "copy" and "paste" method is as follows: Figure 1 shows.
Figure 1. Software containing the same code in multiple places
Seeing the schematic diagram shown in Figure 1, some readers may have discovered this The shortcomings of this approach: If one day, the dark code segment in Figure 1 needs to be modified, then do you need to open the code in three places for modification? What would happen if this code was contained not in 3 places, but in 100, or even 1,000 places?
In order to solve this problem, we usually define the dark code part as shown in Figure 1 as a method, and then call the method in the three code segments respectively. In this way, the structure of the software system is shown in Figure 2.
Figure 2 Implementing system functions through method calls
#For the software system shown in Figure 2, if you need to modify the code in the dark part, just modify One place is enough. No matter how many places in the entire system call this method, the program does not need to modify these places, only the called method can be modified - in this way, the complexity of later maintenance of the software is greatly reduced.
For Method 1, Method 2, and Method 3 shown in Figure 2, you still need to explicitly call the dark method, which can solve most application scenarios. But for some more special cases: the application needs method 1, method 2, and method 3 to be completely separated from the dark method - method 1, method 2, and method 3 do not need to directly call the dark method, so how to solve it?
Because software system requirements change very frequently, only the core business functions were implemented in the early system design method 1, method 2, and method 3. After a period of time, we need to provide methods for method 1, method 2, and method 3. Increase transaction control; after some time, the customer proposed Method 1, Method 2, and Method 3, which required user legality verification, and only legitimate users can execute these methods; after some time, the customer proposed Method 1, Method 2 again , Method 3 should add logging; after a while, the customer asked again... Faced with such a situation, what should we do? There are usually two approaches:
Directly reject the customer's request based on the demand specification.
Embrace needs and meet customer needs.
The first approach is obviously not good. Customers are God, and we should try our best to meet customer needs. The second approach is usually adopted, so how to solve it? Do we define a new method first, then modify method 1, method 2, and method 3, and add new methods to call? The workload of doing this is not small! We hope to have a special method: as long as we define this method, there is no need to explicitly call it in method 1, method 2, and method 3. The system will "automatically" execute this special method.
The above idea sounds magical and even a little unrealistic, but it is actually completely achievable. The technology to achieve this requirement is AOP. AOP is specifically used to deal with cross-concern issues distributed in various modules (different methods) in the system. In Java EE applications, AOP is often used to handle some cross-cutting system-level services, such as transaction management and security checks. , caching, object pool management, etc., AOP has become a very common solution.
Spring AOP principle analysis
You can know from the previous introduction: AOP proxy is actually an object dynamically generated by the AOP framework, which can be used as a target object. The AOP proxy contains all methods of the target object, but the methods in the AOP proxy are different from the methods of the target object: AOP methods add enhanced processing at specific entry points and call back the methods of the target object.
The methods contained in the AOP proxy and the method diagram of the target object are shown in Figure 3.
Figure 3. AOP proxy methods and target object methods
Spring’s AOP proxy is generated and managed by Spring’s IoC container, and its dependencies It is also managed by the IoC container. Therefore, AOP proxies can directly target other bean instances in the container, a relationship provided by the IoC container's dependency injection.
Looking at AOP programming, there are only 3 parts that require programmers to participate:
Definition of common business components.
Define entry points. One entry point may cross multiple business components.
Define enhanced processing, which is a processing action woven into the AOP framework for ordinary business components.
The first part of the above three parts is the most common thing and requires no additional explanation. Then the key to AOP programming is to define entry points and define enhancement processing. Once the appropriate entry point and enhanced processing are defined, the AOP framework will automatically generate an AOP proxy, and the AOP proxy method roughly has the following formula:
Method of the proxy object = Enhanced processing + Method of the proxy object
In the above business definition, it is not difficult to find that the implementation principle of Spring AOP is actually very simple: the AOP framework is responsible for dynamically generating the AOP proxy class, and the methods of this proxy class are composed of Advice and callback target object methods. .
For the software calling structure shown in Figure 2 mentioned earlier: when method 1, method 2, method 3... all need to call a method with "cross-cutting" properties, the traditional approach It is up to the programmer to manually modify Method 1, Method 2, Method 3... and call this "cross-cutting" method through code, but this approach has poor scalability because the code must be changed every time.
So the AOP framework appeared. The AOP framework can "dynamically" generate a new proxy class, and the proxy class contains method 1, method 2, method 3... and also adds the ability to call this A "cross-cutting" method - but this call is taken care of by the proxy class automatically generated by the AOP framework, so it has excellent scalability. Programmers do not need to manually modify the code of method 1, method 2, and method 3. Programmers only need to define the entry point - the AOP proxy class generated by the AOP framework contains new method 1, access method 2, and method 3, and The AOP framework will decide whether to call back methods with "crosscutting" properties in Method 1, Method 2, and Method 3 based on the entry point.
In short: The secret of the AOP principle is to dynamically generate a proxy class, which implements the call in Figure 2 - this call does not require the programmer to modify the code.
summary
AOP is widely used to process some system-level services with cross-cutting properties. The emergence of AOP is a good complement to OOP, which allows developers to handle services with cross-cutting properties in a more elegant way. No matter what kind of AOP implementation, whether it is AspectJ or Spring AOP, they all need to dynamically generate an AOP proxy class. The only difference is the timing of generating the AOP proxy class: AspectJ generates the AOP proxy class at compile time, so it has better performance Performance, but requires the use of a specific compiler for processing; Spring AOP uses runtime to generate AOP proxy classes, so there is no need to use a specific compiler for processing. Since Spring AOP needs to generate an AOP proxy on every run, performance is slightly worse.
For more articles related to the understanding of SpringAOP, please pay attention to the PHP Chinese website!