概念
这里需要提前了解什么是Spring的AOP(Aspect Oriented Programming)。是在OOP(面向对象)思想的一种拓展思想。简单来说就是将某个代码块嵌入到其它的代码块中。笔者先前学Spring也有学什么IoC啊AOP啊,但实际上没有用过、就那听过学过没啥用的。。没会儿就忘记了。那种也就是个了解,好像知道是个什么事儿?当时还特地去背关于AOP的那几个专有名词?现在想想有点好笑。
不过还是需要提前巩固知道几个词。看完了下面的这三个词的用法就开始进入模拟实战。
切面(Aspect):由切点和通知组成。即使用@Aspect注解的类
切点(Pointcut):可以限定访问修饰符、类全限定名、方法名和参数类型,甚至用于匹配注解
通知(Advice):想要嵌入到其它代码块的代码块。其中包括五种类型。
@Before(目标方法执行前执行)
@After(目标方法执行后执行)
@AfterReturning(目标方法返回结果后不出现异常才执行)
@AfterThrowin(出现异常才执行)
@Around(以上都包括)文章来源:https://www.toymoban.com/news/detail-635496.html
引入依赖
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 简化开发 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
创建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
/**
* 描述
*
* @return {String}
*/
String value();
}
业务代码
@Slf4j
@RestController
@RequestMapping("/log")
public class LogController {
@Log("AOP测试")
@GetMapping("/aspect")
public void aspect() {
log.info("进入AOP测试方法");
for(int i = 0; i < 10; ++i) {
log.info("执行业务逻辑{}", i);
}
log.info("结束AOP测试方法");
}
}
编写切面
有切点
@Slf4j
@Component
@Aspect
public class LogAspect {
@Autowired
private ApplicationEventPublisher publisher;
/**
* 切点
* 这里面主要掌握两个东西:
* 1、如果使用注解的话就需要获取注解的类全限定名
* 2、执行的execution表达式(这是比较重要掌握的) 这里面有四个参数 需要知道的是*也可以表示前缀或者后缀 和SQL中的"%"类似
* 一、方法的访问权限修饰符(public/protected/default/private)
* 二、方法的返回值类型
* 三、类的全限定名(包名.类名)
* 四、*(..)的第一个表示方法名;括号内表示参数,而两个点表示接收任何参数类型
*/
@Pointcut("@annotation(com.chf.annotation.Log) && execution(public * com.chf.controller.*Controller.*(..))")
public void logPointcut() {}
@SneakyThrows
@Around("logPointcut()")
public Object around(ProceedingJoinPoint point) {
// 获取注解完后解析其内部的属性
MethodSignature signature = (MethodSignature) point.getSignature();
log.info("获取注解,{}", signature); // void com.chf.controller.LogController.aspect()
Method method = signature.getMethod();
log.info("获取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()
Log logAnnotation = method.getAnnotation(Log.class);
log.info("获取使用注解的value参数,{}", logAnnotation.value()); // AOP测试
// 发送异步事件
Long startTime = System.currentTimeMillis();
Object o;
try {
o = point.proceed();
} finally {
// 这里可以使用发布订阅模式发布异步事件 至于使用哪一种发布订阅模式就看业务场景了
Long endTime = System.currentTimeMillis();
publisher.publishEvent(new LogEvent("事件处理的时间是:" + (endTime - startTime) + "ms"));
}
return o;
}
}
无切点
@Slf4j
@Component
@Aspect
public class LogAspect {
@Autowired
private ApplicationEventPublisher publisher;
@SneakyThrows
@Around("@annotation(logAnnotation) && execution(public * com.chf.controller.*Controller.*(..))")
public Object around(ProceedingJoinPoint point, Log logAnnotation) {
// 获取注解完后解析其内部的属性
MethodSignature signature = (MethodSignature) point.getSignature();
log.info("获取注解,{}", signature); // void com.chf.controller.LogController.aspect()
Method method = signature.getMethod();
log.info("获取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()
Log logAnnotation = method.getAnnotation(Log.class);
log.info("获取使用注解的value参数,{}", logAnnotation.value()); // AOP测试
// 发送异步事件
Long startTime = System.currentTimeMillis();
Object o;
try {
o = point.proceed();
} finally {
Long endTime = System.currentTimeMillis();
publisher.publishEvent(new LogEvent("事件处理的时间是:" + (endTime - startTime) + "ms"));
}
return o;
}
}
测试
不了解Spring的发布订阅模式可以看这篇博文:https://blog.csdn.net/m0_65563175/article/details/131899828?spm=1001.2014.3001.5501文章来源地址https://www.toymoban.com/news/detail-635496.html
到了这里,关于【Spring AOP】结合日志面向切面编程 两种写法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!