由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

Spring—AOP面向切面编程

JAVA 西门飞冰 1125℃

什么是AOP技术

AOP 是一种面向切面的编程思想。面向切面编程是将程序抽象成各个切面,即解刨对象的内部,将那些影响了多个类的公共行为抽取到一个可重用模块里,减少系统的重复代码,降低模块间的耦合度,增强代码的可操作性和可维护性。

AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理、增强处理。

通俗易懂aop是在我们的目标方法之前和之后处理的操作,应用场景在于:日志打印、事务实现、权限控制等

AOP 可以解决我们程序上的代码冗余问题

AOP技术底层原理

AOP 底层基于代理设计模式实现

要想搞懂AOP底层实现原理,就先要搞懂代理设计模式

AOP 常用术语

1、连接点:该类中哪些方法需要被增强,这些方法就可以称作连接点

2、通知(增强)

(1)实际增强的逻辑部分称为通知(增强)

(2)通知有多种类型

  • 前置通知:在方法执行前执行
  • 后置通知:在方法执行后执行
  • 环绕通知:在方法执行前后都执行
  • 异常通知:增强类方法出现异常会通知
  • 最终通知:不管有没有异常都会执行

3、切入点:实际被增强的方法,称为切入点

4、切面:把通知应用到的过程 就是为切面

切入点表达式

1、切入点表达式作用:知道对哪个类里面的哪个方法进行增强

2、语法结构: execution([权限修饰符] [返回类型] [类全路径] 方法名称 )

举例 1:对 com.fblinux.dao.BookDao 类里面的 add 进行增强 execution(* com.fblinux.dao.BookDao.add(..))

举例 2:对 com.fblinux.dao.BookDao 类里面的所有的方法进行增强 execution(* com.fblinux.dao.BookDao.* (..))

举例 3:对 com.fblinux.dao 包里面所有类,类里面所有方法进行增强 execution(* com.fblinux.dao.. (..))

SpringBoot AOP 实现

AOP 环境准备

1.Spring框架一般都是基于AspectJ实现AOP操作

什么是AspectJ?

AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件,AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作.

配置AOP之前在需要在springboot工程目录中引入aspectj包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

SpringBoot配置

目录结构:

image-20220915224649123

测试接口:

@Controller
public class HelloController {
    @GetMapping("/hello")   //用户请求的接口
    @ResponseBody              //代表将字符串作为响应的内容直接返回给客户端
    public String hello(String name){
        return "hello ," + name;
    }
}

配置代码:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;

@Configuration
@Aspect
public class AopConfig {
    /**
     * 前置通知
     */
    @Before("execution(* com.fblinux.aop.controller.HelloController.hello(..));")
    public void before() {
        System.out.println("前置通知...");
    }

    /**
     * 后置通知
     */
    @After("execution(* com.fblinux.aop.controller.HelloController.hello(..));")
    public void after() {
        System.out.println("后通知...");
    }

    /**
     * 环绕通知
     */
    @Around(value = "execution(* com.fblinux.aop.controller.HelloController.hello(..));")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知...");
        System.out.println("目标方法之前开始执行...");
        Object result = proceedingJoinPoint.proceed();
        System.out.println("目标方法之后开始执行...");
        return result;
    }

    //@AfterReturning表达后置通知/返回通知,表达方法返回结果之后执行
    @AfterReturning(value = "execution(* com.fblinux.aop.controller.HelloController.hello(..));")
    public void afterReturning() {
        System.out.println("afterReturning");
    }

    //@AfterThrowing表达异常通知
    @AfterThrowing(value = "execution(* com.fblinux.aop.controller.HelloController.hello(..));")
    public void afterThrowing() {
        System.out.println("afterThrowing");
    }
}

结果验证:

命令行访问接口:

curl http://127.0.0.1:8080/hello?name=fblinux

Idea 控制台验证结果:

image-20220913234751325

相同点抽取

@Pointcut(value = "execution(* com.fblinux.aop.controller.HelloController.hello(..));")
public void pointdemo(){
}

/**
 * 前置通知
 */
@Before(value = "pointdemo()")
public void before() {
    System.out.println("前置通知...");
}

增强优先级设计

有多个增强类多同一个方法进行增强,设置增强类优先级

在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高

spring框架使用那种代理模式

Spring aop底层基于代理模式封装

如果我们被代理类没有实现接口的情况下,则使用cglib动态代理

如果我们被代理类有实现接口的情况下,则使用jdk动态代理

 

转载请注明:西门飞冰的博客 » Spring—AOP面向切面编程

喜欢 (0)or分享 (0)