Spring6 AOP 面向切面编程

1. 概念

  • 面向切面编程:一种编程思想。
  • proxy动态代理(实现了这种思想):在原方法执行时,给原方法的前面或着后面增加其他的方法。增加的方法并不会写在原方法中
    1. 原方法就是目标方法,
    2. 增加的方法就是代理方法
  • 面向切面的好处:
    1. 不必修改原来的代码
    2. 方法中只负责业务的逻辑,像验证、日志、事务管理都可以使用切面解决
  • 面向切面的7个名词:
    1. 连接点:指的是位置,也就是原方法的前面和后面
    2. 切点:在连接点使用的代理方法
    3. 通知:①目标方法之前:前置通知,②目标方法之后:后置通知,③前后都有:环绕通知,④目标方法异常时执行:异常通知,⑤finall里面:最终通知
    4. 切面:
    5. 织入:描述过程。
    6. 目标对象
    7. 代理对象

2. 全注解开发

1. 文件结构

在这里插入图片描述

依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>6.1.14</version>
    </dependency>
    <!-- spring AOP使用的是aspects框架, aspects框架是专业的做切面的框架-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>6.1.14</version>
    </dependency>

2. 目标对象

import org.springframework.stereotype.Component;
// 目标对象
@Component
public class TargetObject {
  public void targetMethod(){
    System.out.println("目标对象执行:................");
  }
}

3. 切面类


@Component
@Aspect // 切面对象
@Order(1) // 目标对象有多个切面对象时,使用Order注解,优先级越小越先执行
public class FirstAopClass {
  // 切点表达式
  @Pointcut("execution(* com.example.service.TargetObject.*(..))")
  public void pointCut() {
  }

  // 前置通知
  @Before("pointCut()")
  public void before(JoinPoint joinPoint) {
    // 除环绕通知外,其他通知都有JoinPoint,从参数中可以获得,类名、方法名、参数等
    System.out.println("前置通知:1");
    // 目标对象的类名
    String targetClassName = joinPoint.getSignature().getDeclaringTypeName();
    // 目标方法的方法名
    String targetMethodName = joinPoint.getSignature().getName();
    // 目标方法的参数
    Object[] args = joinPoint.getArgs();
//    System.out.println("目标对象的类名:" + targetClassName);
//    System.out.println("目标方法的方法名:" + targetMethodName);
//    System.out.println("目标方法的参数:" + Arrays.toString(args));
  }

  // 后置通知
  @AfterReturning("pointCut()")
  public void afterReturning() {
    System.out.println("后置通知:1");
  }

  // 环绕通知
  @Around("pointCut()")
  public void around(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("环绕前置通知:1");
    pjp.proceed(); // 执行目标方法,因为目标方法没有参数,所以不用传参,也没有返回值所以不用return
    System.out.println("环绕后置通知:1");

  }

  // 异常通知:目标方法产生异常才执行此通知
  @AfterThrowing("pointCut()")
  public void afterThrowing() {
    System.out.println("异常通知:1");
  }

  // 最终通知:无论目标方法有没有异常都会执行
  @After("pointCut()")
  public void after() {
    System.out.println("最终通知:1");
  }
}

4. 配置类


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/*
 * @EnableAspectJAutoProxy(proxyTargetClass = true)
 * 1. 动态代理,proxyTargetClass=true 使用 Cglib 动态代理
 * 2. proxyTargetClass不写,默认使用 JDK 动态代理需要有接口
 * */
@Configuration  // 声明这是个用于配置的类(IOC、AOP 都需要使用这个注解指定注解类)
@ComponentScan({"com.example.service"})  // IOC配置: 指定要扫描的包.ioc
@EnableAspectJAutoProxy(proxyTargetClass = true)  // AOP配置,感觉true和false没有区别
public class SpringConfig {}

5. 测试方法

  @Test
  public void test() {
    // 1. 创建IOC容器
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
    // 2. 从IOC容器中获取Bean
    TargetObject targetObject = ctx.getBean("targetObject", TargetObject.class);
    // 3. 执行目标对象中的目标方法,切面方法会自动执行
    targetObject.targetMethod();
  }

6. 执行顺序

环绕前置通知:1
前置通知:1
目标对象执行:................
后置通知:1
最终通知:1
环绕后置通知:1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值