0%

SpringBoot——AOP

动态代理模式

​ SpringBoot动态代理分为两种,一种是JDK的动态代理,另一种是cglib的动态代。Spring Boot默认使用JDK的动态代理,当类没有实现接口时才使用cglib的动态代理。

  1. JDK的动态代理,在这个例子里,被代理类实现了UserService接口,而代理类通过实现与被代理类实现的相同接口UserService,并在内部把被代理类进行注入,就可以实现对被代理类的逻辑增强。
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
interface UserService{
void printUserInfo();
}
class UserServiceImpl implements UserService{

@Override
public void printUserInfo() {
System.out.println("UserInfo print");
}
}

class UserServiceProxy implements UserService{
private UserService userService;

public UserServiceProxy(UserService userService) {
this.userService = userService;
}

@Override
public void printUserInfo() {
System.out.println("========Before Print========");
userService.printUserInfo();
System.out.println("========After Print========");
}
}

public class Proxy {
public static void main(String[] args) {
UserService userService = new UserServiceProxy(new UserServiceImpl());
userService.printUserInfo();
}
}
  1. cglib动态代理,通过自定义拦截器并实现MethodInterceptor 接口来对被代理类进行拦截,并对逻辑进行增强。
1
2
3
4
5
6
7
8
9
10
11
public class AIntercepter implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//增强逻辑
System.out.println("代理前,增强逻辑");
methodProxy.invokeSuper(o, objects);
//增强逻辑
System.out.println("代理后,增强逻辑");
return null;
}
}

AOP的介绍

​ AOP(Aspect Oriented Programing):面向切面编程,将通用的逻辑从业务逻辑中分离出来。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的四周,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP的相关概念

关键词 说明
Joinpoint连接点 表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等
Pointcut切入点 选择一组相关连接点的模式,即可以认为连接点的集合,即符合某种条件的切入点的集合
Advice通知 在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice)。
Introduction引入 也称为内部类型声明,为已有的类添加额外新的字段或方法。
Aspect切面 横切关注点的模块化,比如日志组件。可以认为是通知、引入和切入点的组合。
AOP Proxy AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
Weaving织入 织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。

AOP相关注解

  • @Aspect:表示一个类是一个切面,一个切面包含了通知、切入点等。

  • @Poincut:表示切入的点,即程序中通用的逻辑业务,这里是请求的路径

  • @Before:表示在方法开始执行前执行

  • @After:表示在方法执行后执行

  • @AfterReturning: 表示在方法返回后执行

  • @AfterThrowing: 表示在抛出异常时执行

  • @Around:在方法执行前和执行后都会执行

AOP的使用

  • 简单的使用
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
@Aspect
@Component
@Slf4j
public class PerformanceAspect {
@Around("repositoryOps()")
public Object repoLogPerformance(ProceedingJoinPoint pjp) throws Throwable {
long startTime = System.currentTimeMillis();
String name = "-";
String result = "Y";
try {
name = pjp.getSignature().toShortString();
return pjp.proceed();
}catch (Throwable t){
result = "N";
throw t;
}finally {
long endTime = System.currentTimeMillis();
log.info("{};{};{}ms", name, result, endTime - startTime);
}
}
@After("serviceOps()")
public void serviceLogPerformance(JoinPoint jp){
log.info("================================================");
}
@Pointcut("execution(* com.muchlab.chapter82.repository.CoffeeRepository.findOne(..))")
public void repositoryOps(){

}
@Pointcut("execution(* com.muchlab.chapter82.service.*.*(..))")
public void serviceOps(){

}
}
//execution 表达式的主体
//第一个* 代表任意的返回值
//com.aop所横切的包名
//第二个* 表示类名,代表所有类
//.*(..) 表示任何方法,括号代表参数 .. 表示任意参数
  • 不同的切入点
切入对象 说明
匹配注解 @target 限制连接点匹配特定的执行对象,这些对象对应的类要有具体指定类型的注解
匹配注解 @args 限制连接点匹配参数为指定注解类型的执行方法
匹配注解 @within 限制连接点匹配指定注解所标注的类型
匹配注解 @annotation 限制连接点匹配方法上的注解
匹配包或类型 within 限制连接点匹配指定的表或类
匹配对象 this 限制连接点匹配AOP代理的bean引用为指定类型的类
匹配对象 bean 限制连接点匹配一个指定的bean,需要指出bean的名字
匹配对象 target 限制连接点匹配目标对象为指定类型的类
匹配参数 args 限制连接点匹配参数为指定类型的执行方法
匹配方法 execution() 匹配连接点的执行方法
-------------本文结束感谢您的阅读-------------