Spring AOP——面向切面编程

AOP(Aspect Orient Programming)

1. 什么是AOP

AOP是一种面向切面的编程思想,与OOP相似,同时也是OOP的补充,我们都知道Java是一门面向对象的语言,而这里的面向对象就指的是OOP,而AOP则是Spring中提出的一种编程思想。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。
在这里插入图片描述
AOP能在源代码不修改的情况下对业务进行增强,如增加日志功能,增加事务等

2. AOP的实现原理

AOP是基于动态代理的,可以使用JDK,CGLIB两种代理方式,关于JDK动态代理和CGLIB动态代理可以阅读我的另一篇博客

设计模式之代理模式

AOP实际上是动态代理的规范化,把动态代理的实现步骤,方式都定义好了,让开发人员使用一种统一的方式使用动态代理

3. AOP的常见术语

  1. Aspect: 切面,表示增强的功能,就是一些方法,完成某个功能。非业务功能常见的切面有日志,事务,统计信息,参数检查,权限验证等。
  2. JoinPoint: 连接点,连接业务方法和切面的位置。就是类中的业务方法。
  3. Pointcut: 切入点,指多个连接点方法的集合,多个方法
  4. 目标对象:给哪个类的方法增加功能,这个类就是目标对象
  5. Adive: 通知,通知表示切面功能执行的时间

4. AOP的简单使用

Spring内部实现了AOP规范,但很少使用Spring的AOP实现,因为Spring的AOP比较笨重,我们一般使用aspectJ框架,在Spring中可以直接使用aspectJ框架的功能,aspectJ框架使用AOP的两种方式:
① 使用XML配置文件
② 使用注解方式,一般使用注解方式,有5个注解
使用切面的几个关键的因素:
① 切面的功能代码,切面做什么
② 切面的执行位置,使用Pointcut表示切面位置
③ 切面的执行时间,使用Advice表示时间,在目标代码之前还是之后

注解方式的实现步骤
  1. 导入Maven依赖,除了必要的Spring依赖之外,还需要aspectJ的依赖
<!-- AOP依赖 -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.6</version>
</dependency>
  1. 在Spring配置文件中申明使用动态代理
<!--
    在配置文件中声明 <aop:aspectj-autoproxy proxy-target-class="true" />
    代表使用cglib动态代理,false表示使用JDK动态代理
-->
<aop:aspectj-autoproxy proxy-target-class="true" />
  1. 定义Service类
@Service
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name, Integer age) {
        // 给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
        System.out.println("===目标方法doSome()===");
    }
}
  1. 定义切面类
@Aspect
@Component
public class MyAspect {
	@Before("execution(* *..SomeServiceImpl.*(..))")
    public void myBefore(JoinPoint joinPoint) {
        // 获取方法的完整定义
        System.out.println("方法的签名(定义)=" + joinPoint.getSignature());
        System.out.println("方法的名称=" + joinPoint.getSignature().getName());
        // 获取方法的实参
        Object[] args = joinPoint.getArgs();
        for (Object obj : args) {
            System.out.println(obj);
        }
        // 就是切面要执行的功能代码
        System.out.println("前置通知,切面功能:在目标方法之前输出执行时间:" + new Date());
    }
}

没有使用AOP的执行效果
在这里插入图片描述
使用AOP的执行效果
在这里插入图片描述

5. 通知(Advice)的几种类型

  1. Before Advice 前置通知
    在目标方法之前执行,使用 @Before 注解,可加入JoinPoint参数,通过JoinPoint可以获取到目标方法的签名,包括方法参数、方法名等
  2. After Returning Advice 后置通知
    在目标方式之后执行的,使用 @AfterRunning 注解,可以获取到目标方法的返回值,可以根据这个返回值做不同的功能,可以修改这个返回值
  3. Around Advice 环绕通知
    环绕通知是功能最强大的通知,使用 @Around 注解,方法必须有一个返回值,推荐Object类型的返回值,方法有一个固定的参数ProceedingJoinPoint参数,环绕通知必须要显式地调用ProceedingJoinPoint的proceed方法表示方法的执行,然后再这个方法的执行前后可以加上前置通知功能和后置通知功能,类似于JDK动态代理
  4. After Throwing Advice 异常通知
    在方法抛出异常后执行,使用 @AfterThrowing 注解,有一个Exception类型的参数,表示方法抛出的异常对象,也可以有JoinPoint类型参数
  5. After Advice 最终通知
    在目标方法执行之后执行,使用 @After 注解,可以有JoinPoint类型参数,这个通知总是会执行,目标方法抛出异常后也会执行

6. 切入点表达式

在通知注解上有一个固定属性value,value表示切入点,通常使用切入点表达式来表示切入点的位置,类似于 @Before(value = “execution(public * *(…))”)
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
修饰符模式和异常模式是可选的

  1. execution(public * *(…)) 执行所有以public修饰的方法
  2. execution(* set*(…)) 执行所有的set开头的方法
  3. execution(* cn.xyz.service..(…)) 指定service包下面的任意类中的任意方法
  4. execution(* cn.xyz.service….(…)) 指定在service包或者子包下的任意类的任意方法
  5. execution(* …service..*(…)) 指定所有包下service包的任意类的任意方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值