一文搞懂Spring AOP的五大通知类型

网友投稿 301 2022-07-22


目录一、通知类型二、环境准备添加AOP依赖创建目标接口和实现类创建通知类创建Spring核心配置类编写运行程序三、添加通知普通通知环绕通知(重点)

一、通知类型

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

通知类型注解说明before(前置通知)@Before通知方法在目标方法调用之前执行after(后置通知)@After通知方法在目标方法返回或异常后调用after-returning(返回通知)@AfterReturning通知方法会在目标方法返回后调用after-throwing(异常通知)@AfterThrowing通知方法会在目标方法抛出异常后调用around(环绕通知)@Around通知方法会将目标方法封装起来

二、环境准备

添加AOP依赖

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

org.springframework

spring-context

5.2.10.RELEASE

org.aspectj

aspectjweaver

1.9.5

创建目标接口和实现类

/*UserDao接口*/

public interface UserDao {

http:// public void save();

public int update();

}

/*UserDaoImpl实现类*/

@Repository

public 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();

}

}

运行结果如下

注意点

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

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

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

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

以上就是一文搞懂Spring AOP的五大通知类型的详细内容,更多关于Spring AOP通知类型的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot中@Import注解如何正确使用
下一篇:idea聚合工程搭建过程详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~