Spring——Aop

Spring AOP

什么是AOP?

​        Aspect Oriented Programing ⾯向切⾯编程,相比较 oop ⾯向对象编程来说,Aop关注的不再是程
序代码中某个类,某些⽅法,而aop考虑的更多的是⼀种⾯到⾯的切⼊,即层与层之间的⼀种切⼊,所
以称之为切⾯。联想⼤家吃的汉堡(中间夹肉)。那么aop是怎么做到拦截整个⾯的功能呢?考虑前⾯
学到的servlet filter /* 的配置 ,实际上也是aop 的实现。

AOP能做什么?

       AOP主要应⽤于⽇志记录,性能统计,安全控制,事务处理等方⾯,实现公共功能性的重复使用。

AOP的特点

  1. 降低模块与模块之间的耦合度,提高业务代码的聚合度。(高内聚低耦合)
  2. 提⾼了代码的复⽤性。
  3. 提⾼系统的扩展性。(⾼版本兼容低版本)
  4. 可以在不影响原有的功能基础上添加新的功能

AOP的底层实现

       动态代理(JDK + CGLIB)

AOP基本概念

5.5.1. Joinpoint(连接点)

       被拦截到的每个点,spring中指被拦截到的每⼀个方法,spring aop⼀个连接点即代表⼀个方法的执
⾏。

5.5.2. Pointcut(切入点)

       对连接点进⾏拦截的定义(匹配规则定义 规定拦截哪些⽅法,对哪些方法进⾏处理),spring 有专
⻔的表达式语⾔定义。

5.5.3. Advice(通知)

拦截到每⼀个连接点即(每⼀个方法)后所要做的操作

  1. 前置通知 (前置增强)— before() 执行方法前通知
  2. 返回通知(返回增强)— afterReturn 方法正常结束返回后的通知
  3. 异常抛出通知(异常抛出增强)— afetrThrow()
  4. 最终通知 — after 无论方法是否发⽣异常,均会执行该通知。
  5. 环绕通知 — around 包围⼀个连接点(join point)的通知,如方法调⽤。这是最强⼤的⼀种通知
    类型。 环绕通知可以在方法调⽤前后完成⾃定义的行为。它也会选择是否继续执行连接点或直接
    返回它们⾃⼰的返回值或抛出异常来结束执行。

5.5.4. Aspect(切面)

       切⼊点与通知的结合,决定了切⾯的定义,切⼊点定义了要拦截哪些类的哪些方法,通知则定义了拦
截过方法后要做什么,切⾯则是横切关注点的抽象,与类相似,类是对物体特征的抽象,切⾯则是横切
关注点抽象。

5.5.5. Target(目标对象)

       被代理的⽬标对象

5.5.6. Weave(织入)

       将切⾯应⽤到⽬标对象并⽣成代理对象的这个过程即为织入

5.5.7. Introduction(引入)

       在不修改原有应⽤程序代码的情况下,在程序运⾏期为类动态添加⽅法或者字段的过程称为引⼊

Spring AOP的实现

Spring AOP环境搭建

坐标依赖引⼊

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.4.RELEASE</version>
    </dependency>

添加spring.xml的配置

xmlns:aop="http://www.springframework.org/schema/aop"

			http://www.springframework.org/schema/aop
			http://www.springframework.org/schema/aop/spring-aop.xsd

配置spring.xml文件

<!--配置AOP代理-->
<aop:aspectj-autoproxy/>

切入点:

       匹配规则。规定什么方法被拦截、需要处理什么方法

定义切⼊点

@Pointcut(“匹配规则”)

Aop 切入点表达式简介

  1. 执行任意公共方法:

execution(public *(…))

  1. 执行任意的set方法

execution(* set*(…))

  1. 执行com.xxxx.service包下任意类的任意方法

execution(* com.xxxx.service..(…))

  1. 执行com.xxxx.service 包 以及⼦包下任意类的任意方法

execution(* com.xxxx.service….(…))

注:表达式中的第⼀个* 代表的是方法的修饰范围

可选值:private、protected、public (* 表示所有范围)

通知

@Pointcut("execution(* com.zwx.service..*.*(..))")
    public void queryByName(){}

    /**
    * 声明前置通知 并将通知应⽤到定义的切⼊点上
    * ⽬标类⽅法执⾏前 执⾏该通知
    *
    */
    @Before(value="queryByName()")
    public void before(){
        System.out.println("前置");
    }

    /**
    * 声明返回通知 并将通知应⽤到定义的切⼊点上
    * ⽬标类⽅法(⽆异常)执⾏后 执⾏该通知
    *
    */

    @AfterReturning(value="queryByName()")
    public void afterReturn(){
        System.out.println("返回通知");
    }

    
    /**
      * 声明异常通知 并将通知应⽤到定义的切⼊点上
      * ⽬标类⽅法出现异常时 执⾏该通知
      */
    @AfterThrowing(value="queryByName()")
    public void throwing(){
        System.out.println("异常通知");
    }

    /**
       * 声明最终通知 并将通知应⽤到定义的切⼊点上
       * ⽬标类⽅法(⽆异常或有异常)执⾏后 执⾏该通知
       *
      */
    @After(value="queryByName()")
    public void after1(){
        System.out.println("最终通知");
    }

    /**
    * 声明环绕通知 并将通知应⽤到切⼊点上
    * ⽅法执⾏前后 通过环绕通知定义相应处理
    * 需要通过显式调⽤对应的⽅法,否则⽆法访问指定⽅法 (pjp.proceed();)
    * @param pjp
    * @return
    */	

@Around(value="queryByName()")
    public void around(ProceedingJoinPoint point){
        System.out.println("环绕--前");
        try {
            Object proceed = point.proceed();
            System.out.println("环绕--返回");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕--异常");
        }
        System.out.println("环绕--最终");
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值