通知(增强):被增强的具体功能就是通知
通知分为五种:
1. 前置通知 @Before
2. 后置通知 @AfterReturning
3. 环绕通知(前后都执行) @Around
4. 异常通知(当切入点发生异常时执行) @AfterThrowing
5. 最终通知(相当于异常的finally,也就是说无论如何都会执行) @After
AspectJ
1、Spring 框架一般都是基于 AspectJ 实现 AOP 操作
(1)AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使 用,进行 AOP 操作
2、基于 AspectJ 实现 AOP 操作
(1)基于 xml 配置文件实现
(2)基于注解方式实现(使用)
切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构:
execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )
举例 1:对 com.damo.dao.BookDao 类里面的 add 进行增强
execution(* com.damo.dao.BookDao.add(..))
举例 2:对 com.damo.dao.BookDao 类里面的所有的方法进行增强
execution(* com.damo.dao.BookDao.* (..))
举例 3:对 com.damo.dao 包里面所有类,类里面所有方法进行增强
execution(* com.damo.dao.*.* (..))
在项目工程里面引入 AOP 相关依赖
下面实操
- 进行通知的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.company.spring5.*"/>
<!--开启AspectJ自动代理对象-->
<aop:aspectj-autoproxy/>
</beans>
- 创建一个被增强的类,在类里面定义方法
package com.company.spring5.aopDemo.dao;
import org.springframework.stereotype.Component;
/** 被增强的类 */
@Component
public class BookDaoImpl {
public Integer add(Integer a, Integer b) {
System.err.println("add方法。。。");
return a / b;
}
}
- 创建增强类(编写增强逻辑) ,在增强类里面,创建方法,让不同方法代表不同通知类型
package com.company.spring5.aopDemo.proxies;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/** 增强的类 */
@Component
@Aspect // 生成代理对象
public class BookProxy {
/** 前置通知 使用切入点表达式配置切入点 */
@Before("execution(* com.company.spring5.aopDemo.dao.BookDaoImpl.add(..))")
public void before() {
System.err.println("before->前置通知执行。。。");
}
/** 后置通知 */
@AfterReturning("execution(* com.company.spring5.aopDemo.dao.BookDaoImpl.add(..))")
public void afterReturning() {
System.err.println("afterReturning->后置通知执行。。。");
}
/** 异常通知 */
@AfterThrowing("execution(* com.company.spring5.aopDemo.dao.BookDaoImpl.add(..))")
public void afterThrowing() {
System.err.println("afterThrowing->异常通知执行。。。");
}
/** 最终通知 */
@After("execution(* com.company.spring5.aopDemo.dao.BookDaoImpl.add(..))")
public void after() {
System.err.println("after->最终通知执行。。。");
}
/**
* 环绕通知
*
* <p>环绕通知比较特殊,需要一个ProceedingJoinPoint对象参数,ProceedingJoinPoint有一个proceed()方法,而proceed()方法即使我们的切入点
* proceedingJoinPoint.proceed();执行切入点方法
*
* <p>在切入点前后执行增强的逻辑代码
*/
@Around("execution(* com.company.spring5.aopDemo.dao.BookDaoImpl.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.err.println("around->环绕通知执行---->方法执行前。。。");
proceedingJoinPoint.proceed();
System.err.println("around->环绕通知执行---->方法执行后。。。");
}
}
- 创建一个test类并测试代码
package com.company.spring5;
import com.company.spring5.aopDemo.dao.BookDaoImpl;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
void testAop() {
// 加载bean
ApplicationContext context = new ClassPathXmlApplicationContext("aop-bean.xml");
BookDaoImpl bookDaoImpl = context.getBean("bookDaoImpl", BookDaoImpl.class);
bookDaoImpl.add(1, 1);
}
}
- 测试结果:
以上结果并没有异常通知,因为我们并没有异常,下面添加一个异常看结果:
结束语:以上即是 spring-aop通知的五种类型以及结合AspectJ简单用法
希望对你有所帮助😄