Spring-AOP

本文详细介绍了Spring AOP(面向切面编程)的核心概念,包括连接点、切入点、通知、切面等,并阐述了AOP的开发过程。通过XML配置和注解方式展示了如何定义切入点、通知类型以及织入过程。同时,文中还提供了AOP在实际应用中的场景,如数据验证、异常处理等。
摘要由CSDN通过智能技术生成

Spring-AOP

AOP(面向切面编程)开发思想:主要是指提取出多个功能之间的共性部分(重复)。

AOP相关概念

  • 连接点:方法

  • 切入点:被挖掉共性功能的方法

  • 通知:共性功能提出来单独成一个类

  • 切面:描述切入点和通知的关系(例如在代码的那个位置被挖走)

  • 目标对象:被挖掉功能的方法所属的类

  • 织入:将共性功能放回简化功能中组成完整的功能。这是一个动态过程

  • 代理:织入过程运行的位置。这个位置是原始的目标对象创建的代理类

AOP开发过程

  • 开发阶段(开发者完成)

    • 正常的制作程序

    • 将非共性功能开发到对应的目标对象类中,并制作成切入点方法

    • 将共性功能独立开发出来,制作成通知

    • 在配置文件中,声明切入点

    • 在配置文件中,声明切入点通知间的关系(含通知类型),即切面

  • 运行阶段(AOP完成)

    • Spring容器加载配置文件,监控所有配置的切入点方法的执行

    • 当监控到切入点方法被运行,使用代理机制,动态创建目标对象代理对象,根据通知类别,在代理对象的对应位置将通知对应的功能织入,完成完整的代码逻辑并运行

AOP相关坐标

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<!--文件中还要添加命名空间-->

AOP配置(XML方式)

  • AOP配置简例

    <!--aop配置 可以配置多个,都会生效-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* *..*())"/>
        <!--配置切面-->
        <aop:aspect ref="填写通知(共性功能)的bean">
            <!—通知与切入点之间的关系-->
            <aop:before method="通知中具体的一个方法" pointcut-ref="pt"/>
        </aop:aspect>
    </aop:config>
    
  • 切入点(本质就是一个方法)

    • <aop:pointcut id="pt" expression="execution(* *..*())"/>
      
    • 关键字(访问修饰符 返回值 包名.类名(接口名).方法名(参数)异常名)

    • 例子:

      execution(public User com.itheima.service.UserService.findById(int))
      
    • *:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

      execution(public * com.itheima.*.UserService.find*(*))
      
    • … :多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

      execution(public User com..UserService.findById(..))
      
    • +:专用于匹配子类类型

      execution(* *..*Service+.*(..))
      
  • 切入点的配置位置

    • <aop:config>
          <!--配置公共切入点-->
          <aop:pointcut id="pt1" expression="execution(* *(..))"/>
          <aop:aspect ref="myAdvice">
              <!--配置局部切入点-->
              <aop:pointcut id="pt2" expression="execution(* *(..))"/>
              <!--引用公共切入点-->
              <aop:before method="logAdvice" pointcut-ref="pt1"/>
              <!--引用局部切入点-->
              <aop:before method="logAdvice" pointcut-ref="pt2"/>
              <!--直接配置切入点-->
              <aop:before method="logAdvice" pointcut="execution(* *(..))"/>
          </aop:aspect>
      </aop:config>
      

通知类型

  • 前置通知 aop:before

    • 原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行

    • 应用场景:数据检验

    • <aop:aspect ref="adviceId">
          <aop:before method="methodName" pointcut="……"/>
      </aop:aspect>
      
    • 标签内属性

      • method :在通知类中设置当前通知类别对应的方法
      • pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
      • pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
  • 后置通知 aop:after

    • 原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知

    • 应用场景:处理执行现场

    • <aop:aspect ref="adviceId">
          <aop:after method="methodName" pointcut="……"/>
      </aop:aspect>
      
    • 标签内属性同上

  • 返回后通知 aop:after-returning

    • 原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行

    • 应用场景:返回值的相关数据处理

    • <aop:aspect ref="adviceId">
          <aop:after-returning method="methodName" pointcut="……"/>
      </aop:aspect>
      
  • 抛出异常通知 aop:after-throwing

    • 原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行

    • 应用场景:对原始方法中出现的异常信息处理

    • <aop:aspect ref="adviceId">
          <aop:after-throwing method="methodName" pointcut="……" throwing="t"/>
      </aop:aspect>
      <!--在通知方法中参数写上Throwable t,可以得到返回的异常对象-->
      
  • 环绕通知 aop:around

    • 在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行

    • 应用场景:做任何事情

    •  <aop:aspect ref="adviceId">    <aop:around method="methodName" pointcut="……"/></aop:aspect>
      
    • 环绕通知是在原始方法的前后添加功能,在环绕通知中,存在对原始方法的显式调用

      public Object around(ProceedingJoinPoint pjp) throws Throwable {
          Object ret = pjp.proceed();
          return ret;
      }
      
      • 上诉代码说明:必须设定参数ProceedingJoinPoint对象,通过该对象调用proceed()方法,实现对原始方法的调用。
      • 使用proceed()方法调用原始方法时,因无法预知原 始方法运行过程中是否会出现异常,强制抛出Throwable对象,封装原始方法中可能出现的异常信息

通知中获取参数

获取参数方法一

使用JoinPoint对象

//通知方法
public void before(JoinPoint jp) throws Throwable {
    Object[] args = jp.getArgs();
}

获取参数方法二

在通知方法中:参数和原始方法写同类型

在xml配置中稍作修改如下:

<aop:before method = "before" 
            arg-names = "y,a"
            pointcut = "execution(* *..*(int,int)) &amp;$amp; args(x,y)"/>
<!--使用arg-names可以交换参数顺序-->
<!--在字符中,&用转义字符&amp;-->

AOP配置(注解)

AOP配置的注解方式,所有注解全部配置在通知上

AOP注解驱动扫描:@EnableAspectJAutoProxy配置在spring核心配置类上

AOP注解驱动扫描:aop:aspectj-autoproxy/

  • @Aspect 切面注解,配置在通知类上。此类同时还要配置@Component
  • @Pointcut(“execution(”),配置在一个方法上,此方法没有方法体,没有参数,没有返回值
  • @Before(“此处填写切入点注解配置的那个无参无返回值的方法名”),此外还有@After @AfterReturning @AfterThrowing @Around
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值