AOP:面向切面编程,可以在不影响源代码的情况下对方法进行动态增强
事务:日常开发中经常碰到的一个问题,假如程序出现了异常,可能会导致提交到数据库不一致的情况发生。所以需要事务来解决,事务需要掌握ACID四个特性
以前使用原生的Spring去配置AOP和事务有点麻烦,需要些一大堆的配置文件,而Spring Boot可以对这些内容进行简化,基本是达到零配置,所以在这里使用Spring Boot来配置AOP和事务
更多精彩的文章请访问我的个人博客网站:http://lzmweb.cn
使用AOP首先要对AOP一些常见的概念要有所了解:
Joinpoint(连接点):连接点就是我们想要去增强的方法,该方法就是一个连接点
Pointcut(切入点):对Joinpoint(连接点)进行拦截的定义即为切入点
Advice(通知):当拦截到Joinpoint(连接点)之后我们所需要做的就是通知了,每个通知都是一个方法,通知分为:
前置通知(Before):在增强方法调用之前实现,例如我想对一个aop()方法进行增强,那么前置通知方法就是会在aop()方法之前执行
返回通知(AfterReturning):返回通知可以得到增强方法的返回值
异常通知(AfterThrowing):异常通知是在方法发生异常的时候调用的,可以从中获取异常信息
后置通知(After):后置通知就是一个方法最后执行完毕的时候执行的,不管方法有没有发生异常,它都会执行
Aspect(切面):通知是一个类,Pointcut(切入点)和Advice(通知)的结合
Spring Boot版本选择2.3.1,导入整合的AOP依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
<version>2.3.1.RELEASEversion>
dependency>
AOP的作用是在不影响源代码的情况下对方法进行动态增强,而一般需要增强的地方是在Service层,所以我们先创建一个Service层的类
import org.springframework.stereotype.Service;
@Service
public class UserService {
public String aop(){
System.out.println("方法正常调用");
return "返回一个字符串";
}
}
定义切面类,切面类需要加上@Component和@Aspect注解,在类里面定义切入点表达式和通知。这里需要注意切入点表达式的写法,这样写的意思是识别impl包下的所有类的所有方法。
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserAspect {
//切入点表达式
@Pointcut("execution(* cn.zhku.admin.service.impl.*.*(..))")
public void pc(){
}
//前置通知
@Before(value = "pc()")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法AOP前置通知");
}
//后置通知
@After(value = "pc()")
public void after(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法AOP后置通知");
}
//返回通知
@AfterReturning(value = "pc()",returning = "result")
public void afterReturning(JoinPoint joinPoint,Object result){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法AOP返回通知,返回值为:"+result);
}
//异常通知
@AfterThrowing(value = "pc()",throwing = "e")
public void afterThrowing(JoinPoint joinPoint,Exception e){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法AOP异常通知,异常信息为:"+e.getMessage());
}
}
在测试类中运行测试,主要是使用UserService实例调用被增强的方法
import cn.zhku.admin.service.impl.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class AopTest {
@Autowired
private UserService userService;
@Test
void testAop(){
userService.aop();
}
}
查看运行结果,可以看到整个执行流程
尝试手动制造异常,在被增强的方法中加入int i = 1 /0,再运行查看结果
在介绍完AOP之后,现在再来看事务。我们在开发中经常会遇到一个问题,如果我在提交数据到数据库的过程中发生了异常,可能会导致我的数据发生了改变,但是因为异常的原因,数据库中却没有更新数据。为了避免这种问题发生,我们需要使用事务来解决。
事务四大特性(ACID):
我们需要在主启动类中加上@EnableTransactionManagement注解,表示开启事务管理
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@SpringBootApplication
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
然后在我们需要进行事务管理的方法加上@Transactional注解即可
@Transactional
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println(name+"方法AOP前置通知");
}
AOP和事务这两部分内容非常的重要,在以前使用Spring去配置的时候非常复杂,但是有了Spring Boot之后,使用起来就非常方便了!