AOP 面向切面编程-------面向特定方法编程

而AOP面向方法编程,就可以做到在不改动这些原始方法的基础上,针对特定的方法进行编程,可以是功能增强也可以是功能的改变

AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行增强(无侵入性: 解耦)

AOP的优势:

  1. 减少重复代码

  2. 提高开发效率

  3. 维护方便

一. 怎么实现

1. 在pom文件中导入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.创建一个aop包用于管理aop

package com.xxxx.aop;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Slf4j
@Aspect //标志当前类是一个aop类
public class TimeAspect {

    //下面代码作用在那些方法上 当执行service层的.*(接口或者类)中的*(..)方法时都会执行下面共性的逻辑
    @Around("execution(* com.itheima.service.*.*(..))")     //切入点表达式
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
        //1.记录开始时间
        long begin = System.currentTimeMillis();

        //2 调用原始方法执行
        //原始方法的返回值
        Object result = joinPoint.proceed();

        //3 记录书记兼,计算方法执行耗时
        //获取原始方法的签名----joinPoint.getSignature()
       log.info(joinPoint.getSignature()+"方法执行耗时:{}", System.currentTimeMillis()-begin);



        return result;

    }
}

二 . AOP核心概念

1. 连接点:JoinPoint,可以被AOP控制的方法,连接点指的是可以被aop控制的方法。这里就是service中接口或者类中的所有方法

就是控制哪个包下的方法

2. 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)

就是这一块,将所有方法中重复的逻辑集中到一起

3. 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用---就是切入点表达式所有方法中实际被应用的方法

4. 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)

5. 目标对象:Target,通知所应用的对象

目标对象指的就是通知所应用的对象,我们就称之为目标对象。

三. 执行流程

 一旦我们进行了基于aop程序的开发,最开始执行的就不是原始的对象,而是基于动态代理技术的动态代理对象

四. AOP 通知类型

Spring中AOP的通知类型:

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

 1,抽取切入点表达式

@Slf4j
@Component
@Aspect
public class MyAspect1 {

    //切入点方法(公共的切入点表达式)        如果想要别的方法也可以使用该表达式方法的修饰符要改成 public
    @Pointcut("execution(* com.itheima.service.*.*(..))")
    private void pt(){

    }

    //前置通知(引用切入点)
    @Before("pt()")
    public void before(JoinPoint joinPoint){
        log.info("before ...");

    }

    //环绕通知
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around before ...");

        //调用目标对象的原始方法执行
        Object result = proceedingJoinPoint.proceed();
        //原始方法在执行时:发生异常
        //后续代码不在执行

        log.info("around after ...");
        return result;
    }

    //后置通知
    @After("pt()")
    public void after(JoinPoint joinPoint){
        log.info("after ...");
    }

    //返回后通知(程序在正常执行的情况下,会执行的后置通知)
    @AfterReturning("pt()")
    public void afterReturning(JoinPoint joinPoint){
        log.info("afterReturning ...");
    }

    //异常通知(程序在出现异常的情况下,执行的后置通知)
    @AfterThrowing("pt()")
    public void afterThrowing(JoinPoint joinPoint){
        log.info("afterThrowing ...");
    }
}
@Slf4j
@Component
@Aspect
public class MyAspect2 {
    //引用MyAspect1切面类中的切入点表达式
    @Before("com.itheima.aspect.MyAspect1.pt()")
    public void before(){
        log.info("MyAspect2 -> before ...");
    }
}

 

五,多个切面类执行顺序

切面方法类名排名越靠前 before执行越靠前

after执行顺序越靠后

使用注解 在切面类上加上order来改变顺序

@Order(2)  //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋进的大马猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值