深入理解AOP思想

简介: 深入理解AOP思想

AOP



概念 : AOP为Aspect Oriented Programming的缩写, 意思为切面编程。


他是一种可以在不修改原来核心代码的情况下给程序动态统一进增强的一种技术


springAOP : 批量对spring容器中的bean的方法做增强,并且这种增强不会与原来方法中的代码耦合


依赖


<dependency>
  <groupId>org.aspect</groupId>
  <artifactId>aspectjweaver</artifactId>
    <version>1.8.13</version>
</dependency>


快速入门实现


定义切面类

@Component  //将类交给容器去管理
@Aspect  //作用 : 告诉Spring容器,这是一个切面类
public class MyAspect{  
}


切入点


@Component  //将类交给容器去管理
@Aspect  //作用 : 告诉Spring容器,这是一个切面类
public class MyAspect{  
    //定义切入点
    @Pointcut("execution("需要增强的路径地址")")
    public void pt(){}
    //在被调用的方法之前执行
    @Before("pt()")  //增强是针对哪些方法
    public void methodbefore(){
    }
}


aop核心概念


连接点 : 【joinpoint】所谓的连接点就是能够被增强到的点,在spring中 只支持方法类型的连接点


切入点 : 【pointcut】所谓的切入点,就是指被增强的连接点


**通知/增强 :【Advice】 **所谓的通知是指jurisdiction增强的代码


**目标对象 : 【Target】 **被增强的对象就是目标对象


切面: 【Aspect】: 是指切入点 和通知(引介) 的 结合


**代理 : 【Proxy】 **一个类被aop增强后,所产生一个结果的代理类


切入点


1.**切入点表达式: **image-20230320191539415.png



举例:


image-20230320191636878.png


2.切点函数(用的不多)

我们可以在要增强的方法上加上注解。然后使用@annotation来表示对加了什么注解的方法进行增强。


image-20230320192100758.png



/**
 * 自定义注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SystemLog {
    String businessName();
}


1.在自定义注解上需要加

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)


2.在需要被注解增强的相关方法上加上我们自定义的注解的注解名就可以实现增强

3.在切面类上进行添加切入点等信息

image-20230320192458549.png


通知


几种通知的分类


image-20230320192755168.png



package tech.pdai.springframework.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
/**
 * @author pdai
 */
public class LogAspect {
    /**
     * 环绕通知.
     *
     * @param pjp pjp
     * @return obj
     * @throws Throwable exception
     */
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-----------------------");
        System.out.println("环绕通知: 进入方法");
        Object o = pjp.proceed();
        System.out.println("环绕通知: 退出方法");
        return o;
    }
    /**
     * 前置通知.
     */
    public void doBefore() {
        System.out.println("前置通知");
    }
    /**
     * 后置通知.
     *
     * @param result return val
     */
    public void doAfterReturning(String result) {
        System.out.println("后置通知, 返回值: " + result);
    }
    /**
     * 异常通知.
     *
     * @param e exception
     */
    public void doAfterThrowing(Exception e) {
        System.out.println("异常通知, 异常: " + e.getMessage());
    }
    /**
     * 最终通知.
     */
    public void doAfter() {
        System.out.println("最终通知");
    }
}


环绕通知


如何使用 ?


@Around("pt()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-----------------------");
        System.out.println("环绕通知: 进入方法前");
        Object o = pjp.proceed();
        System.out.println("环绕通知: 退出方法后");
        return o;
    }


注意点 : 如果目标方法有返回值 ,那么对应的切面类中的环绕通知的方法也必须有返回值


AspectJ注解方式


基于XML的声明式AspectJ存在一些不足,需要在Spring配置文件配置大量的代码信息,为了解决这个问题,Spring 使用了@AspectJ框架为AOP的实现提供了一套注解。

YV50V_WRUQXY{8(IEUQ97WU.png


获取被增强方法相关信息


我们实际对方法进行增强时往往还需要获取到被增强方法的相关信息,比如 : 方法名,参数,返回值,异常信息….


我们除了在环绕通知外的所有通知方法中增加一个JoinPoint类型的参数。这个参数封装了被增强方法的相关信息 。我们还可以通过这个参数获取到除了异常对象 和返回值 之外的所有信息。


image-20230320194616436.png


image-20230320195321351.png


//对于controller层的方法增强
private void handleBefore(ProceedingJoinPoint joinPoint) {
    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = requestAttributes.getRequest();
    //获取被增强方法上的注解对象
    SystemLog systemLog = getSystemLog(joinPoint);
    log.info("============Start============");
    // 打印请求 URL
    log.info("URL            : {}",request.getRequestURL());
    // 打印描述信息
    log.info("BusinessName   : {}",systemLog.businessName());
    // 打印 Http method
    log.info("HTTP Method    : {}",request.getMethod());
    // 打印调用 controller 的全路径以及执行方法
    log.info("Class Method   : {}.{}",joinPoint.getSignature().getDeclaringTypeName(),((MethodSignature) joinPoint.getSignature()).getName());
    // 打印请求的 IP
    log.info("IP             : {}",request.getRemoteHost());
    // 打印请求入参
    log.info("Request Args   : {}", JSON.toJSONString(joinPoint.getArgs()) );
}


//对于service层的方法增强
private void handleBefore(ProceedingJoinPoint joinPoint) {
         String className = joinPoint.getSignature().getDeclaringTypeName();
        System.out.println("获取 类名:  " + className);
        String methodName = joinPoint.getSignature().getName();
        System.out.println("获取方法名 : "  + methodName);
        Object[] args = joinPoint.getArgs();
        System.out.println("获取参数;" + Arrays.toString(args));
        System.out.println("获取参数(转为json格式);" + JSON.toJSONString(args));
}


异常


image-20230320202111363.png


多切面增强顺序


通过@Order的大小来规定多个切面的顺序


image-20230320203705453.png


参考学习说明:


视频学习 : 三更springAOP


相关资料参考 :https://pdai.tech/md/spring/spring-x-framework-aop.html



目录
相关文章
|
3月前
|
数据库
AOP(面向切面编程)的基本概念和原理
AOP(面向切面编程)的基本概念和原理
257 0
|
3月前
彻底整垮Aop面向切面编程的原理和使用
彻底整垮Aop面向切面编程的原理和使用
|
3月前
|
SQL 缓存 Java
【Spring】AOP底层原理(动态代理)-》 AOP概念及术语 -》 AOP实现
【Spring】AOP底层原理(动态代理)-》 AOP概念及术语 -》 AOP实现
64 0
|
Java 测试技术 数据安全/隐私保护
Springloc和aop的基础概念
Springloc和aop的基础概念
|
安全 编译器 数据安全/隐私保护
谈谈对 AOP 的理解
谈谈对 AOP 的理解
72 0
|
Java Spring 容器
|
Java 数据安全/隐私保护 Spring
Spring | AOP思想(上)
Spring | AOP思想(上)
|
Java Spring
Spring | AOP思想(下)
Spring | AOP思想(下)
|
设计模式 数据采集 Java
java设计模式之代理设计模式(Spring核心思想AOP的底层设计模式)
代理设计模式 🍅 作者:程序员小王 🍅 程序员小王的博客:程序员小王的博客 🍅 扫描主页左侧二维码,加我微信 一起学习、一起进步 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线
110 0
java设计模式之代理设计模式(Spring核心思想AOP的底层设计模式)
|
Java 开发者
AOP 的概念|学习笔记
快速学习AOP 的概念
83 0
AOP 的概念|学习笔记