18.AOP开发

 

AOP开发

AOP面向切面开发

可以对一个对象里面的某一个或某一些方法进行增强

创建项目并引入aop的starter

1
2
3
4
5
      <!-- aop starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

创建Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.springframework.stereotype.Service;

@Service
public class TestService {

public String doLogic(String inputParam) {
System.out.println("inputParam -> doLogic()");
return "success";
}

public String doException() {
System.out.println("convert Integer");
Integer a = Integer.valueOf("2.80");
return "fail";
}
}

创建切面类

前置通知和后置通知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.example.demo.aspect;

import java.util.Iterator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
@Aspect
// @EnableAspectJAutoProxy: default true
public class MyAspect {

/*
* 声明切面
*/
@Pointcut(value = "execution(* com.example.demo.service.*.*(..))")
public void pc() {

}

@Before(value = "pc()")
public void beforeFun() {
System.out.println("init the parameter");
}

@After(value = "pc()")
public void afterFun() {
System.out.println("insert the log");
}

}

环绕通知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.Iterator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
@Aspect
// @EnableAspectJAutoProxy: default true
public class MyAspect {

/*
* 声明切面
*/
@Pointcut(value = "execution(* com.example.demo.service.*.*(..))")
public void pc() {

}

public void beforeFun() {
System.out.println("init the parameter");
}

public void afterFun() {
System.out.println("insert the log");
}

@Around(value = "pc()")
public void aroundFun(ProceedingJoinPoint joinPoint) {
try {
beforeFun();
// 执行目标方法
joinPoint.proceed();
afterFun();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.service.TestService;

@SpringBootTest
class ApplicationTests {

@Autowired
private TestService testService;

@Test
void contextLoads() {
testService.doLogic("param1");
}
}
1
2
3
init the parameter
inputParam -> doLogic()
insert the log

异常通知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.example.demo.aspect;

import java.util.Iterator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
@Aspect
// @EnableAspectJAutoProxy: default true
public class MyAspect {

/*
* 声明切面
*/
@Pointcut(value = "execution(* com.example.demo.service.*.*(..))")
public void pc() {

}

/*
* throwing = "throwable"的属性值"throwable"
* 必须与errFun(Throwable throwable)的形参名throwable相同
*/
@AfterThrowing(pointcut = "pc()", throwing = "throwable")
public void errFun(Throwable throwable) {
System.out.println("exception");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.service.TestService;

@SpringBootTest
class ApplicationTests {

@Autowired
private TestService testService;

@Test
void contextLoads() {
testService.doException();
}

}
1
2
convert Integer
exception

获取目标函数的参数和返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.util.Iterator;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Component
@Aspect
// @EnableAspectJAutoProxy: default true
public class MyAspect {

/*
* 声明切面
*/
@Pointcut(value = "execution(* com.example.demo.service.*.*(..))")
public void pc() {

}

public void beforeFun() {
System.out.println("init the parameter");
}

public void afterFun() {
System.out.println("insert the log");
}

@Around(value = "pc()")
public void aroundFun(ProceedingJoinPoint joinPoint) {
try {
beforeFun();

// 获取参数
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
System.out.println("parameter" + (i+1) + ": " + args[i]);
}
// 执行目标方法并获取返回值
Object result = joinPoint.proceed();
System.out.println("return: " + result);

afterFun();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.service.TestService;

@SpringBootTest
class ApplicationTests {

@Autowired
private TestService testService;

@Test
void contextLoads() {
testService.doLogic("param1");
}
}
1
2
3
4
5
init the parameter
parameter1: param1
inputParam -> doLogic()
return: success
insert the log