Spring AOP的5种通知类型
Posted 流楚丶格念
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP的5种通知类型相关的知识,希望对你有一定的参考价值。
AOP通知类型
1. AOP通知分类
AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置
- AOP通知共分为5种类型
- 前置通知:在切入点方法执行之前执行
- 后置通知:在切入点方法执行之后执行,无论切入点方法内部是否出现异常,后置通知都会执行。
- ==环绕通知(重点):==手动调用切入点方法并对其进行增强的通知方式。
- 返回后通知:在切入点方法执行之后执行,如果切入点方法内部出现异常将不会执行。
- 抛出异常后通知:在切入点方法执行之后执行,只有当切入点方法内部出现异常之后才执行。
2. AOP通知详解
2.1 前置通知
- 名称:@Before
- 类型:方法注解
- 位置:通知方法定义上方
- 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
- 范例:
@Before("pt()")
public void before()
System.out.println("before advice ...");
2.2 后置通知
- 名称:@After
- 类型:方法注解
- 位置:通知方法定义上方
- 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
- 范例:
@After("pt()")
public void after()
System.out.println("after advice ...");
2.3 返回后通知
- 名称:@AfterReturning(了解)
- 类型:方法注解
- 位置:通知方法定义上方
- 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法正常执行完毕后运行
- 范例:
@AfterReturning("pt()")
public void afterReturning()
System.out.println("afterReturning advice ...");
2.4 抛出异常后通知
- 名称:@AfterThrowing(了解)
- 类型:方法注解
- 位置:通知方法定义上方
- 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行
- 范例:
@AfterThrowing("pt()")
public void afterThrowing()
System.out.println("afterThrowing advice ...");
2.5 环绕通知
- 名称:@Around(重点,常用)
- 类型:方法注解
- 位置:通知方法定义上方
- 作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
- 范例::
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable
System.out.println("around before advice ...");
Object ret = pjp.proceed();
System.out.println("around after advice ...");
return ret;
环绕通知注意事项
- 环绕通知方法形参必须是ProceedingJoinPoint,表示正在执行的连接点,使用该对象的proceed()方法表示对原始对象方法进行调用,返回值为原始对象方法的返回值。
- 环绕通知方法的返回值建议写成Object类型,用于将原始对象方法的返回值进行返回,哪里使用代理对象就返回到哪里。
- 环绕通知中可以对原始方法调用过程中出现的异常进行处理
- 环绕通知可以隔离原始方法的调用执行
3. 代码案例
项目结构如下:
导入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yyl</groupId>
<artifactId>spring_20_aop_advice_type</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
</project>
编写配置类,开启切面编程配置
package com.yyl.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@ComponentScan("com.yyl")
@EnableAspectJAutoProxy
public class SpringConfig
编写接口与实现类
package com.yyl.dao;
public interface BookDao
public void update();
public int select();
package com.yyl.dao.impl;
import com.yyl.dao.BookDao;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao
public void update()
System.out.println("book dao update is running ...");
public int select()
System.out.println("book dao select is running ...");
// int i = 1/0;
return 100;
编写通知类,我们使用5种通知类型 分别配置 update与save方法上
package com.yyl.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAdvice
@Pointcut("execution(void com.yyl.dao.BookDao.update())")
private void pt()
@Pointcut("execution(int com.yyl.dao.BookDao.select())")
private void pt2()
//@Before:前置通知,在原始方法运行之前执行
@Before("pt()")
public void before()
System.out.println("before advice ...");
//@After:后置通知,在原始方法运行之后执行
@After("pt2()")
public void afterpt2()
System.out.println("after advice ...");
//@After:后置通知,在原始方法运行之后执行
@After("pt()")
public void afterpt()
System.out.println("after advice ...");
//@Around:环绕通知,在原始方法运行的前后执行
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable
System.out.println("around before advice ...");
//表示对原始操作的调用
Object ret = pjp.proceed();
System.out.println("around after advice ...");
return ret;
@Around("pt2()")
public Object aroundSelect(ProceedingJoinPoint pjp) throws Throwable
System.out.println("around before advice ...");
//表示对原始操作的调用
Integer ret = (Integer) pjp.proceed();
System.out.println("around after advice ...");
return ret;
//@AfterReturning:返回后通知,在原始方法执行完毕后运行,且原始方法执行过程中未出现异常现象
@AfterReturning("pt2()")
public void afterReturning()
System.out.println("afterReturning advice ...");
//@AfterThrowing:抛出异常后通知,在原始方法执行过程中出现异常后运行
@AfterThrowing("pt2()")
public void afterThrowing()
System.out.println("afterThrowing advice ...");
运行结果如下图所示:
接下来我们将save中的除0操作取消注释
int i = 1/0;
再运行,发现运行异常通知
以上是关于Spring AOP的5种通知类型的主要内容,如果未能解决你的问题,请参考以下文章