写点什么

【Spring 学习笔记 (十三)】Spring AOP 五大通知类型

作者:倔强的牛角
  • 2022 年 6 月 18 日
  • 本文字数:2342 字

    阅读完需:约 8 分钟

【Spring 学习笔记(十三)】Spring AOP 五大通知类型

写在前面😘

大一电子信息工程新生,请多多关照,希望能在 InfoQ 社区记录自己的学习历程!

【Spring 学习笔记】 系列教程基于 Spring 5.2.10.RELEASE讲解。

一、通知类型

Advice 直译为通知,也有人翻译为 “增强处理”,共有 5 种类型,如下表所示。


二、环境准备

添加 AOP 依赖

pom.xml文件里添加 Spring AOP AspectJ 的 jar 包依赖


<dependencies>    <!--包含Spring AOP:有基本的AOP功能-->    <dependency>        <groupId>org.springframework</groupId>        <artifactId>spring-context</artifactId>        <version>5.2.10.RELEASE</version>    </dependency>    <!--AspectJ框架有更强大的AOP功能-->    <dependency>        <groupId>org.aspectj</groupId>        <artifactId>aspectjweaver</artifactId>        <version>1.9.5</version>    </dependency></dependencies>
复制代码

创建目标接口和实现类

/*UserDao接口*/public interface UserDao {    public void save();    public int update();}/*UserDaoImpl实现类*/@Repositorypublic class UserDaoImpl implements UserDao {    @Override    public void save() {        System.out.println("正在执行 UserDao 的 save 方法");    }    @Override    public int update() {        System.out.println("正在执行 UserDao 的 update 方法");        return 1;    }}
复制代码

创建通知类

  • 创建通知类,并指定切入点


/*通知类*/@Component//将这个类定义成 Bean@Aspect//将这个Bean定义为切面public class MyAdvice {    //指定UserDao类中的save方法为切入点    @Pointcut("execution(void com.bighorn.dao.UserDao.save())")    private void pt1(){}    //指定UserDao类中的update方法为切入点    @Pointcut("execution(int com.bighorn.dao.UserDao.update())")    private void pt2(){}}
复制代码

创建 Spring 核心配置类

/*Spring核心配置类*/@Configuration@ComponentScan("com.bighorn") //开启注解扫描@EnableAspectJAutoProxy //开启 AspectJ 的自动代理public class SpringConfig {}
复制代码

编写运行程序

public class App {    public static void main(String[] args) throws SQLException {        //获取配置类初始化容器        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);        //从容器中获取UserDao对象        UserDao userDao = context.getBean(UserDao.class);        //调用userDao的方法        userDao.save();    }}
复制代码

三、添加通知

普通通知

MyAdvice这个通知类中添加前置通知后置通知返回后通知异常后通知及相关注解。


//前置通知@Before("pt1()")public void before() {    System.out.println("before advice ...");}//后置通知@After("pt1()")public void after() {    System.out.println("after advice ...");}//返回后通知@AfterReturning("pt1()")public void afterReturning() {    System.out.println("afterReturning advice ...");}//异常后通知@AfterThrowing("pt1()")public void afterThrowing() {    System.out.println("afterThrowing advice ...");}
复制代码


  • 观察运行 App 程序后的截图,发现并没有显示异常后通知



  • 手动在save()方法中添加一行代码:int i = 1/0,造成异常后再次运行 App。

  • 发现异常后通知有了,但是运行后通知却消失了。



  • 综上所述: 前置通知和后置通知是一定会执行的,而返回后通知是需要在原始方法正常执行后才会被执行,异常后通知是需要原始方法抛出异常才会被执行

环绕通知(重点)

环绕通知非常强大的通知,能够完成上述四种通知的所有功能


/**     * 环绕通知需要携带ProceedingJoinPoint类型的参数     * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法     * 环绕通知必须要有返回值,返回值即为目标方法的返回值     * @param pjp     * @return Object     */@Around("pt2()")public Object around(ProceedingJoinPoint pjp) {    Object result = null;    try {        System.out.println("这是环绕通知中的前置通知......");        //执行目标方法        result = pjp.proceed();        System.out.println("这是环绕通知中的返回通知......");    } catch (Throwable e) {        System.out.println("这是环绕通知中的异常通知......");    }    System.out.println("这是环绕通知中的后置通知......");    return result;}
复制代码


修改 App 类,调用 UserDao 的update()方法,运行程序,观察结果。


public class App {    public static void main(String[] args) throws SQLException {        //获取配置类初始化容器        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);        //从容器中获取UserDao对象        UserDao userDao = context.getBean(UserDao.class);        //调用userDao的update方法        userDao.update();    }}
复制代码


运行结果如下👇


注意点
  1. 使用环绕通知必须传入形参ProceedingJoinPoint,并使用pjp.proceed()方法实现对原始方法的调用,进而实现原始方法调用前后同时添加通知

  2. 通知中如果未使用使用pjp.proceed()方法实现对原始方法的调用,则将跳过原始方法的执行

  3. 原始方法的返回值类型决定环绕通知的返回值类型。原始方法若不接收返回值,通知方法的返回值类型可以设置成 void,也可以设置成 Object;如果接收返回值,最好设定为 Object 类型

  4. 由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须要处理 Throwable 异常

写在后面🍻

感谢观看啦✨

有什么不足,欢迎指出哦💖

发布于: 刚刚阅读数: 6
用户头像

把学问造就,还期身健行优。 2022.06.02 加入

大一在读,电子信息工程专业。 希望在InfoQ写作社区记录自己的学习历程!

评论

发布
暂无评论
【Spring 学习笔记(十三)】Spring AOP 五大通知类型_Java_倔强的牛角_InfoQ写作社区