我们在学习Spring的时候,总是会看到Spring对于AOP的支持,这同IOC一起,属于Spring的两大核心。既然是核心,这AOP又有哪些应用场景呢?
相信很多小伙伴都知道:权限控制、事务管理、记录日志等。
那么基于这些应用场景,我们如何去自定义满足场景业务的AOP呢?
好的,咱们废话少说,直接开撸!
AOP的组成
首先我们来看看,自定义一个最简单的AOP,需要哪些步骤
1、定义切面类Aspect
:所有有关切面的操作实现都可以在这个类中完成;
2、寻找切入点Pointcut
:根据自己的场景业务及代码结构,寻找合适的切入点,在这个切入点前后,我们会加入自定义的增强操作;
3、增强处理Advice
:所谓增强处理,就是具体的场景业务实现,可以是调用方法之前的权限判断,可以是执行方法前后的事务处理,也可以是执行某项操作后的日志记录。
自定义AOP实现
准备工作,需要先加入AOP的pom引用,,如果是Spring Boot的开发者可以使用下面的引用方式👇
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
这是Spring Boot已经封装好的,实际上最终引用的是org.aspectj
的包
接下来就是激动人心的开发环节
1、定义切面类
按照刚刚介绍的步骤,首先我们需要定义一个切面类,这很简单,只需要在创建的类名上加上@Aspect
注解就可以了,需要注意的是引用的包名org.aspectj.lang.annotation.*
2、寻找切入点
第二步就是根据自己的场景业务,寻找一个切入点。
比如说:我需要记录用户表User
的操作日志,那么我这里就可以将所有有关用户表的增删查改当作切入点,而对于用户的所有操作方法,我都是写在UserService
里面,所以切入点选他就完事儿了。
然后通过@Pointcut
注解来选中刚刚我们分析得来的切入点,具体写法,就可以像下面这样写👇
当然,切入点的匹配方式还有很多种,可以根据自己的业务自行选择:
- execution:用于匹配方法执行的连接点;
- this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
- within:用于匹配指定类型内的方法执行;
- @within:用于匹配所以持有指定注解类型内的方法;
- target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
- @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
- args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
- @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
- @annotation:用于匹配当前执行方法持有指定注解的方法。
3、增强处理
最后一步,就是定义增强处理来完成场景业务逻辑。增强方式也有很多种,我们这里选择“前置增强@Before
”和“后置增强@After
”,然后在增强方法里面控制台打印调用的方法和方法传参
到这一步我们的自定义AOP就算完成了,运行一下单元测试,看看控制台打印结果
切面类完整代码如下
package com.jorkeycloud.integration.aop;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Aspect
@Component
public class DiyAspect {
@Pointcut("this(com.jorkeycloud.integration.service.UserService)")
public void diyPointCut(){}
@Before("diyPointCut()")
public void beforeCut(JoinPoint joinPoint) {
System.err.println("method name: "+joinPoint.getSignature().getName());
System.err.println("method args: ");
Arrays.stream(joinPoint.getArgs()).forEach(arg -> {
System.err.println(JSONObject.toJSONString(arg));
});
System.err.println("----====---->前置增强");
}
@After("diyPointCut()")
public void afterCut(JoinPoint joinPoint) {
System.err.println("----====---->后置增强");
}
}
以上demo仅供参考,如有说的不对的地方,欢迎下方评论区讨论 (^ _ ^)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)