Spring-AOP-5种通知

一、AOP术语

  1. 连接点
    类里面的那些可以被增强的方法,这些方法称为连接点

  2. 切入点
    实际被正真增强的方法,称为切入点

一个类里面有四个方法,但是只增强两个,那么这两个就是切入点

  1. 通知(增强)
    实际增强的逻辑部分称为通知(增强),其中通知有五种类型。

就是增加的部分,比如简约的登录功能,在功能里加入的权限判断就是增强的部分。

  • ① 前置通知:切入点方法执行之前执行的方法@Before
  • ② 返回通知:切入点方法执行之后执行的方法@AfterReturning:可以得到切入点执行的返回值,有异常后就不执行
  • ③ 环绕通知:切入点前后都执行 @Around
  • ④ 异常通知:切入发点方法执行异常后执行的方法@AfterThrowing:切入点里面的出现异常如10/0,才会执行的方法。
  • ⑤ 后置通知:相当于Java中的try/cath中的finally,不论前面执行结果如何,都会执行的方法 @After:执行后执行,有没有日常都执行。
  1. 切面
    (动词)
    把通知应用到切入点

  2. 切入点表达式
    切入点表达式的作用:知道对那个类里面的哪个方法进行增强
    语法结构:
    execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]))

二、AOP实践-AspectJ

  1. 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
  1. Spring配置文件
    proxy-target-class="true"表示使用cglib动态代理
    实现动态代理有两种形式:
    ① jdk动态代理:根据目标类接口获取代理类实现规则,生成代理对象。这个代理对象,也是目标类接口的一个实现类。
    ② cglib动态代理:根据目标类本身获取代理类实现规则,生成代理对象。这个代理对象,也是目标类的一个子类。 (如果目标类为final,则不能使用CGLib实现动态代理)
    SpringAOP可以自动在jdk动态代理和CGLib动态代理之间进行切换,规则如下:
  • 如果目标对象实现了接口,采用jdk动态代理实现aop。
  • 如果目标对象没有实现接口,采用CGLib动态代理实现aop。
  • 如果目标对象实现了接口,但仍然想要使用CGLIB实现aop,可以手动进行配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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-4.1.xsd">
<!--开启注解扫描,设置需要扫描的包 -->
<context:component-scan base-package="com.du.AopTest.anno"/>
<!-- 声明自动为spring容器中那些配置@Aspect切面的bean创建代理,织入切面。 -->
<aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
  1. 通知
package com.du.AopTest.anno;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserAop {
@Pointcut("execution(* com.du.AopTest.anno.User.eat(..))")
public void exe() {}
@Before(value = "exe()")
public void before(){
System.out.println("before......");
}
@After(value = "exe()")
public void after() {
System.out.println("after......");
}
@AfterReturning(pointcut = "exe()",returning = "result")
public void afterReturning(Object result) {
System.out.println("afterReturning......");
System.out.println("afterReturning-result:"+result);
}
@AfterThrowing(pointcut = "exe()",throwing = "ex")
public void afterThrowing() {
System.out.println("AfterThrowing......");
System.out.println("ex");
}
@Around(value = "exe()")
public void around(ProceedingJoinPoint p) throws Throwable{
System.out.println("around......前");
Object object = p.proceed();
System.out.println("around......object:"+object);
System.out.println("around......后");
}
}
  1. Test
public class UserMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext("config.xml");
User user = c.getBean("user",User.class);
user.eat();
}
}

关于切入点方法,就一个类,里面一个方法
5. 控制台

  • 没有异常出现
    image

  • 切入点方法有异常出现
    image

  1. 注意JoinPoint可以得到很多信息
    如果你给通知加个形参
package com.du.AopTest.anno;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserAop {
@Pointcut("execution(* com.du.AopTest.anno.User.eat(..))")
public void exe() {}
@Before(value = "exe()")
public void before(JoinPoint j){
System.out.println("before......");
Signature s = j.getSignature();
System.out.println(s.getName());
System.out.println(s.toString());
System.out.println(s.getModifiers());
}
}

结果:
image

posted @   生生灯火半杯月  阅读(610)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示