浅析Spring基于注解的AOP
目录
- 一、准备工作
- 二、基于注解的AOP之前置通知
- 三、基于注解的AOP之切入点表达式的语法和重用以及获取连接点的信息
- ①切入点表达式的语法
- ②获取连接点的信息
- ③重用写入点表达式
一、准备工作
①创建一个Maven工程
②添加依赖
在IOC所需依赖基础上再加入下面依赖即可:
<!-- spring-aspects会帮我们传递过来aspectjweaver --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.1</version> </dependency>
③把上节的接口和实现类复制过来,因为我们要在这个环境里面测试
二、基于注解的AOP之前置通知
如果我们要实现AOP的话,它也是要在我们的IOC的基础上实现的,所以说我们必须要把切面还有目标对象交给IOC容器来管理
AOP 抽横切关注点(非核心业务代码)
①创建切面类并配置
/** * 在切面中,需要通过指定的注解将方法标识为通知方法 * @Before:前置通知,在目标对象方法执行之前执行 */ @Component @Aspect //将当前组件标识为切面 public class LoggerAspect { @Before("execution(public int com.tian.spring.aop.annotation.CalculatorImpl.add(int,int))") public void beforeAdviceMethod() { System.out.println("LoggerAspect,前置通知"); } }
②创建Spring配置文件,让ioc对我们的目标对象进行管理
<!-- AOP的注意事项: 切面类和目标类都需要交给IOC容器管理 切面类必须通过@Aspect注解标识为一个切面 在Spring的配置文件中设置<aop:aspectj-autoproxy />开启基于注解的AOP --> <context:component-scan base-package="com.tian.spring.aop.annotation"></context:component-scan> <!--开启基于注解的AOP--> <aop:aspectj-autoproxy/>
测试类:
public class AOPTest { @Test public void testAOPByAnnotation() { ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml"); Calculator calculator = ioc.getBean(Calculator.class); calculator.add(1,2); } }
三、基于注解的AOP之切入点表达式的语法和重用以及获取连接点的信息
1.在切面中,需要通过指定的注解将方法标识为通知方法
@Before:前置通知,在目标对象方法执行之前执行
2.切入点表达式:设置在标识通知的value属性中
execution(public int com.tian.spring.aop.annotation.CalculatorImpl.add(int,int))
execution(* com.tian.spring.aop.annotation.CalculatorImpl.*(..))
第一个*表示任意的访问修饰符和返回值类型
第二个*表示类中任意的方法
..表示任意的参数列表
类的地方也可以使用*,表示包下所有的类
①切入点表达式的语法
上述已经将我们的前置通知,通过切入点表达式作用到了我们的连接点上,下面我们来说是细节问题,因为我们设置得还不是很完美,就比如上面实现了后只能作用与我们的add方法,因为我们的切入点表达式是写死了的,下面我就来进行更完美的代码实现
将切面类中的切入点表达式修改为如下
/** * * 切入点表达式:设置在标识通知的value属性中 * execution(public int com.tian.spring.aop.annotation.CalculatorImpl.add(int,int)) * execution(* com.tian.spring.aop.annotation.CalculatorImpl.*(..)) * 第一个*表示任意的访问修饰符和返回值类型 * 第二个*表示类中任意的方法 * ..表示任意的参数列表 * 类的地方也可以使用*,表示包下所有的类 */ @Component @Aspect //将当前组件标识为切面 public class LoggerAspect { // @Before("execution(public int com.tian.spring.aop.annotation.CalculatorImpl.add(int,int))") @Before("execution(* com.tian.spring.aop.annotation.*.*(..))") public void beforeAdviceMethod() { System.out.println("LoggerAspect,前置通知"); } }
测试类:
public class AOPTest { @Test public void testAOPByAnnotation() { ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml"); Calculator calculator = ioc.getBean(Calculator.class); calculator.sub(1,2); } }
②获取连接点的信息
获取连接点的信息
在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息 获取连接点所对应方法的签名信息
Signature signature = joinPoint.getSignature();
获取连接点所对应方法的参数
Object[] args = joinPoint.getArgs();
System.out.println("LoggerAspect,方法:" + signature.getName() + ",参数" + Arrays.toString(args));
我们在之前的动态代理里面,我们在前置通知的位置,也就是在我们目标对象的方法执行之前,然后我们在方法体中输出的是我们要调用的方法的方法名,还有就是我们当前的参数列表,但是我们用了前置通知之后,我们不知道如何获取了,还没有我们动态代理实现的功能多。而且连接点的信息我们都获取不到,也就是我当前要加入通知的方法,它的一些信息我们都获取不到。其实我们也是可以获取到的,下面我就来实现
// @Before("execution(public int com.tian.spring.aop.annotation.CalculatorImpl.add(int,int))") // @Before("execution(* com.tian.spring.aop.annotation.*.*(..))") @Pointcut("pointCut()") public void beforeAdviceMethod(JoinPoint joinPoint) { //获取连接点所对应方法的签名信息 Signature signature = joinPoint.getSignature(); //获取连接点所对应方法的参数 Object[] args = joinPoint.getArgs(); System.out.println("LoggerAspect,方法:" + signature.getName() + ",参数" + Arrays.toString(args)); }
③重用写入点表达式
重用切入点表达式
//@Pointcut声明一个公共的切入点表达式
@Pointcut("execution(* com.tian.spring.aop.annotation.CalculatorImpl.*(..))") public void pointCut() {}
使用方式:@Pointcut("pointCut()")
声明
@Pointcut("execution(* com.tian.spring.aop.annotation.CalculatorImpl.*(..))") public void pointCut() { }
引用
@After("pointCut()") public void afterAdviceMethod() { }
到此这篇关于浅析Spring基于注解的AOP的文章就介绍到这了,更多相关Spring AOP内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!