SpringAop
不讲解基础概念,从一个实例入手AOP
1.引入依赖
<!--spring context依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.18</version>
</dependency>
<!--spring aspects依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.9</version>
</dependency>
2.spring配置文件中添加context命名空间和aop命名空间,配置组件扫描,开启代理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="com.example.jenkinspro.service"/>
<!--开启自动代理-->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
3.定义目标类以及目标方法
@Component
public class UserService {
public void login(){
System.out.println("登录 .....");
}
}
4.在切面类中添加通知
@Component
@Aspect
public class userAspect {
@Before("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect(){
System.out.println("我是日志前置通知");
}
}
补充:切点表达式:
上面的切点表达式:修饰符省略,所有返回值,指定类,类下所有的方法。
如果切点是在包下,可以使用俩个点,如下所示
execution( * com.example.jenkinspro.service..*(..)):切的是service 包下所有的类
execution([访问控制权限修饰符] 返回值 类型 [全限定类名]方法名(形式参数列表) [异常])
5.输出
我是日志前置通知
登录 .....
6.通知类型
前置通知:
@Before("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect(){
System.out.println("我是日志前置通知");
}
输出:
我是日志前置通知
登录 .....
后置通知:
@AfterReturning("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect2(){
System.out.println("我是日志后置通知");
}
输出:
登录 .....
我是日志后置通知
环绕通知:
@Around("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect3(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("我是环绕前通知");
joinPoint.proceed();
System.out.println("我是环绕后通知");
}
输出:
我是环绕前通知
登录 .....
我是环绕后通知
异常通知
在发生异常的时候,就会触发这个异常
@AfterThrowing("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect4(){
System.out.println("我是异常通知");
}
最终通知
@After("execution( * com.example.jenkinspro.service.UserService.*(..))")
public void aspect5(){
System.out.println("最终通知");
}
7.切面的执行顺序
当有多个切面的时候,那么顺序是怎么决定的呢?
在切面类使用注解
@Order(1) //设置优先级,数字越小,优先级越高
8.连接点: