Location>code7788 >text

What is AOP and Customizing AOP in Springboot

Popularity:487 ℃/2024-08-17 15:24:47

AOP (Aspect Oriented Programming) is generally translated as Cutting-edge Oriented Programming.

Aspect [ˈæspekt] n. aspect; dimension; (verb of) body
So what exactly does AOP Faceted Cutting Programming mean, and how does it differ from and relate to the previous OOP Faceted Object Programming.
First of all, OOP, Faceted Object Programming simply means that everything can be considered as an object, and all we have to do is to abstract everything (virtual objects in the business logic), into a single object, and then enrich these abstract objects with various capabilities and properties (methods and attributes). Thus, we can abstract a whole section of business logic as our system.

But in the process of OOP development, we found that although we have abstracted a lot of objects, but some of the methods between the object is some commonality, if further abstraction, the overall abstraction granularity is too small, the abstraction granularity is too complex. In this case, we need to change the perspective of these common points, as a point of entry, will be injected into our business logic to directly enhance these entry points. And this enhanced object of a commonality point of programming, we call it AOP, that is, faceted faceted programming. (Anti-theft connection: this article was first published from /jilodream/ )

An example:

Teachers in schools need to count classroom hours every day, civil servants in the government need to count office hours every day, and at the same time, computers in the office need to count the number of hours they are turned on every day.

They are all essentially objects, and if we count the daily runtime, we now have two ways to accomplish this:

1, each to realize their own statistical approach, simple to implement, but complex to modify, and there are a lot of duplication of logic.

2, the definition of a unified interface, teachers, civil servants, computers to achieve the same interface, which reduces the duplication of logic, but then the implementation of complexity, the whole abstraction granularity is too fine.

At this point we can be programmed through AOP, the teacher, civil servants, the office of the machine, as an entry point, in this entry point to do some processing work outside the object. This is called cut-oriented programming. It looks a bit like cheating, so many people see aop as a complement to object-oriented programming. It's a third-party perspective on object-oriented programming, as shown below:

Let's take a look at how to implement cut-oriented programming in the most popular java framework springboot framework:
Faceted cutout programming implements three basic operations:
1, set the entry surface Aspect (where to put)
2. Write additional capabilities, i.e., new features to be injected into the business logic (what to put in)
3, weaving in, that is, the new features injected into the original business logic. (How to put in)
Suppose we now have a simple Springboot project that implements the concatenation of two strings:

First we add the relevant pom dependencies:

1         <dependency>
2             <groupId></groupId>
3             <artifactId>spring-boot-starter-aop</artifactId>
4         </dependency>
5         <dependency>
6             <groupId></groupId>
7             <artifactId>aspectjweaver</artifactId>
8             <version>1.9.7</version>
9         </dependency>

Then we follow the 3 basic operations to add aop capabilities:

1. Setting the entry surface
There are two common ways to set up a cutout, and we'll look at them in turn
(1) Use of annotated forms

 1 package ;
 2 
 3 
 4 import ;
 5 import ;
 6 import ;
 7 import ;
 8 
 9 @Target()
10 @Retention()
11 public @interface LogAop {
12 }

As above first define an annotation: @Target, we set to method, @Retention, we set to runtime, the annotation can be tagged to the method, while the runtime to use the annotation. (about java's annotations, belong to the basics of java, but in the emerging framework, his role is more and more, I will take the time to write an article about it)

Define the following cutout class:
Define a cut method at will, with the annotation @PointCut for the method, marking the fully qualified class name of the annotation to be added.
Then we can set the entry point at the cutout we want to set, as follows

1 public class AopAdvice {
2 
3     @Pointcut("execution(* (..))")
4     public void logAopCut() {
5         int a=1;
6         ("point cut 123 " );
7         //  ("ex advice1");
8     }
9 }

The business code adds defined annotations like this, in red font:

1     @LogAop // like this
2     @Override
3     public String learnMinus(String para1, String para2) {
4         //   ("start Minus");
5         ("service learn minus "+para1 +para2 );
6         return para1 + "-" + para2;
7     }

This approach is more in line with the current programming ideas, (anti-theft connection: this article was first published from /jilodream/ ) as far as possible to use a variety of annotations to replace the original various configurations to reduce the difficulty of maintaining the configuration.

(2) Using Execution Expressions
Instead of defining annotations, we can set, directly on the cut method, the point to cut to, as follows:

1 public class AopAdvice {
2 
3     @Pointcut("execution(* (..))")
4     public void logAopCut() {
5         int a=1;
6         ("point cut 123 " );
7         //  ("ex advice1");
8     }
9 }

The part after execution we use is called the execution expression.

This is a regular-like expression with the following general structure

The question mark part can be filled in or not, and we can use *,... to achieve fuzzy matching.

* can fuzzy match, a certain level of options, or a certain level of part of the options, such as we want to omit a certain level of package names, you can also omit a certain part of the method name.
... Can be used to omit multilevel options.
Due to space constraints, we won't go into execution expressions too much here.
This allows us to directly specify a certain level method as the entry point based on the fully qualified path.
There are two things to note here:
If the annotation expression is used, the annotation is added to the interface, it is not possible to add an entry point in the implementation class, in other words it will not take effect directly.
Note: When using execution expressions, if the expression matches a parent class or interface, the entry point for the corresponding subclass is in effect. Here is also and java annotations will not inherit directly, inherit class and interface implementation class, but can replace the class and interface in the method is an effect.

2. Preparation of empowerment
Let's go ahead and add the following method to the OPTAopAdvice class:

The annotations for the methods can be used in sequence
@Before Cutting Facet Execution Execution
@After After the return of the entry surface
@Around Cut-in Surround
@AfterReturning After a normal return of the entry surface
@AfterThrowing After the return of a cut-plane exception
@After is inclusive of both @AfterReturning @AfterThrowing scenarios.
Like the following, we can define several enhancements

 1 public class AopAdvice {
 2 
 3   
 4     @Before("logAopCut()")
 5     public Object logBefore() {
 6         ("log before !!!" );
 7         return "123456654rjdkkgjlkjg";
 8     }
 9 
10     @Before("optAopCut()")
11     public Object optBefore() {
12         ("opt before !!!" );
13         return "123456654rjdkkgjlkjg";
14     }
15 
16     @After("optAopCut()")
17     public void optAfter() {
18         ("opt after !!!" );
19 
20     }
21 
22     @After("logAopCut()")
23     public void logAfter() throws Throwable {
24         ("log after !!!" );
25 
26     }
27 
28     @Around("optAopCut()")
29     public Object optAround1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
30         ("around start1 " );
31         Object proceed = ();
32         ("around end1 " );
33         return proceed;
34     }
35 
36     @Around("optAopCut()")
37     public Object optAround2(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
38         ("around start2 " );
39         Object proceed = ();
40         ("around end 2" );
41         return proceed;
42     }
43 }

3、Weave in
This step is theoretically the most complex, but and specific business logic and the furthest away, (anti-theft connection: this article was first published from /jilodream/ ) so spring has long been encapsulated for us!
All we need to do is add the OPTAopAdvice class to the@Aspect @Component, respectively, to perform cutover processing, and to perform springboot bean management.

The overall code is as follows:

controller layer

 1 package ;
 2 
 3 import .slf4j.Slf4j;
 4 import ;
 5 import ;
 6 import ;
 7 import ;
 8 
 9 import ;
10 
11 /**
12  * @discription
13  */
14 @Slf4j
15 @RestController
16 public class Controller {
17 
18     @Autowired
19     private DoService doService;
20 
21     @Autowired
22     private DoServiceImpl doServiceImpl;
23 
24     @Deprecated
25     @GetMapping("/learn/add")
26     public String learnAdd(@RequestParam("para1") String para1, @RequestParam("para2") String para2) {
27         //   ("show plugin Profile {} ,{}", para1, para2);
28         ("controller learn add " + para1 + para2);
29         return (para1, para2) + (para1, para2);
30     }
31 
32     @Deprecated
33     @GetMapping("/learn/minus")
34     public String learnMinus(@RequestParam("para1") String para1, @RequestParam("para2") String para2) {
35         //   ("show plugin Profile {} ,{}", para1, para2);
36         ("controller learn Minus " + para1 + para2);
37         Date date = new Date();
38         return (para1, para2) + () + () + "";
39     }
40 
41 }

service layer

 1 package ;
 2 
 3 /**
 4  * @discription
 5  */
 6 public interface DoService {
 7 
 8     String learnAdd(String para1, String para2);
 9 
10 
11     String learnMinus(String para1,  String para2);
12 
13 }

 

 1 package ;
 2 
 3 
 4 import .slf4j.Slf4j;
 5 import ;
 6 
 7 /**
 8  * @discription
 9  */
10 @Slf4j
11 @Service
12 public class DoServiceImpl implements DoService {
13     @Override
14     public String learnAdd(String para1, String para2) {
15         ("service learn add "+para1 +para2 );
16         return para1 + "+" + para2;
17     }
18 
19     @OPTAop
20     @Override
21     public String learnMinus(String para1, String para2) {
22         //   ("start Minus");
23         ("service learn minus "+para1 +para2 );
24         return para1 + "-" + para2;
25     }
26     
27     @Override
28     public void learnNothing() {
29         ("service learn do nothing  " );
30 
31     }
32 }

The service port we set to 8081.

Request the following url

http://127.0.0.1:8081/learn/minus?para1=1a&para2=2b

The console output is as follows

 1 controller learn Minus 1a2b
 2 around start1 
 3 around start2 
 4 log before !!!
 5 opt before !!!
 6 service learn minus 1a2b
 7 opt after !!!
 8 log after !!!
 9 around end 2
10 around end1 

Notice two details here

1. The order of execution.

bound is executed first, then before, after and then back to bound, which means that before and after are closer to the cut-points, which is something we need to take into account when dealing with scenarios such as distributed locking.

2. Multiple methods can be added at a single entry point.

The cut order is generally added in the order in which the code is loaded (written in the order it is written), and despite the fact that multiple enhancement methods are added at a single entry point, the code on the entry side is only executed once. (What is his principle? How to mimic or implement it, I'll go into more detail later)

There's more to the above, so let's summarize it here.

1, aop is an object-oriented supplement, is for the common characteristics of multiple objects, we unify a way to enhance the ability.

2, custom aop programming as long as the implementation of the 3 parts: set the entry point, write enhancements, weave in