Spring AOP是什么?
AOP(面向切面编程):将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为"切面"(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;
在Spring AOP中,切面由切点(Pointcut)和通知(Advice)组成。切点是一个表达式,用于匹配哪些方法需要被横切,通知是在切点位置执行的代码,表示横切逻辑。
++切点表达式配置语法:++
execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
execution(public void com.apesource.service.ServiceImp.findAll())
- 修饰符可以省略代表任意 execution(返回值 包名称.类名称.方法名称(参数列表))
- 返回值可以使用"*"代表任意 execution(* 包名称.类名称.方法名称(参数列表))
- 包名可以使用"*"代表任意名称 execution(* *.*.*.类名称.方法名称(参数列表))
- 包名可以使用".."代表任意个数 execution(* *...类名称.方法名称(参数列表))
- 类名与方法名可以使用"*"代表任意 execution(* *...*.*(参数列表))
- 参数列表可以使用".."代表任意个数任意类型 execution(* *...*.*(..))
如果有参数 int======>int String===>java.lang.String
++Spring AOP提供了几种常见的通知类型,包括:++
- 前置通知(Before):在方法执行前执行的逻辑
- 后置通知(After):在方法执行后执行的逻辑
- 返回通知(After-returning):在方法成功返回后执行的逻辑
- 异常通知(After-throwing):在方法抛出异常后执行的逻辑
- 环绕通知(Around):在方法执行前后都可以执行的逻辑,可以控制目标方法的执行流程
Spring AOP 基于动态代理实现:
- 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象;
- 如果被代理的对象,没有实现某个接口, Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理;
Spring AOP可以通过注解或XML配置的方式来定义切点和通知,并且可以与Spring的IOC容器无缝集成,使得切面和目标对象的创建和管理变得更加简单。
1⃣️XML
1.添加依赖:
java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.28</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
2.创建切面类:
java
public class LoggerUtil {
//前置通知
public void beforeMethod(){
System.out.println("前置通知=====>"+new Date());
}
//返回通知
public void afterRrturnMethod(){
System.out.println("返回通知=====>"+new Date());
}
//异常通知
public void throwMethod(){
System.out.println("异常通知=====>"+new Date());
}
//后置通知
public void afterMethod(){
System.out.println("后置通知=====>"+new Date());
}
//环绕通知
public Object arroundMethod(ProceedingJoinPoint pjp){
Object obj = null;
try {
//环绕通知---前置通知
System.out.println("环绕通知---前置通知");
Object[] objs = pjp.getArgs();
obj = pjp.proceed(objs);
//环绕通知---返回通知
System.out.println("环绕通知---返回通知");
} catch (Throwable throwable) {
//环绕通知---异常通知
System.out.println("环绕通知---异常通知");
throwable.printStackTrace();
} finally {
//环绕通知---后置通知
System.out.println("环绕通知---后置通知");
}
return obj;
}
}
3.配置XML:
XML
<!--开启aop配置-->
<aop:config>
<!--切面-->
<aop:aspect id="mian" ref="loggerUtil">
<!--切点-->
<aop:pointcut id="dian" expression="execution(* *...*.*(..))"/>
<!--通知-->
<aop:before method="beforeMethod" pointcut-ref="dian"></aop:before>
<aop:after-returning method="afterRrturnMethod" pointcut-ref="dian"></aop:after-returning>
<aop:after-throwing method="throwMethod" pointcut-ref="dian"></aop:after-throwing>
<aop:after method="afterMethod" pointcut-ref="dian"></aop:after>
<aop:around method="arroundMethod" pointcut-ref="dian"></aop:around>
</aop:aspect>
</aop:config>
2⃣️注解
1.添加依赖:
java
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.28</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
2.创建切面类:
java
@Component
@Aspect//切面
//@EnableAspectJAutoProxy
public class LoggerUtil {
//切点
@Pointcut(value="execution(* com.apesource.service.*.*(..))")
public void dian(){}
//前置通知
// @Before("dian()")
public void beforeMethod(){
System.out.println("前置通知=====>"+new Date());
}
//返回通知
// @AfterReturning("dian()")
public void afterRrturnMethod(){
System.out.println("返回通知=====>"+new Date());
}
//异常通知
// @AfterThrowing("dian()")
public void throwMethod(){
System.out.println("异常通知=====>"+new Date());
}
//后置通知
// @After("dian()")
public void afterMethod(){
System.out.println("后置通知=====>"+new Date());
}
//环绕通知
@Around("dian()")
public Object arroundMethod(ProceedingJoinPoint point){
Object returnObj = null;//执行切点方法
try {
System.out.println("环绕通知====>前置通知");
//切点
Object[] obj = point.getArgs();//切点方法的参数
returnObj = point.proceed(obj);
System.out.println("环绕通知====>返回通知");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("环绕通知====>异常通知");
} finally {
System.out.println("环绕通知====>后置通知");
}
return returnObj;//切点方法的返回值
}
}
3.配置XML:(也大可不配直接注解)
XML
<!--aop的自动代理 @EnableAspectJAutoProxy可以替换标签-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>