Spring AOP

在 Spring AOP 中,主要有以下几种类型的切面:

  1. 前置通知(Before advice):在目标方法执行之前执行的通知。前置通知不会阻止目标方法的执行,除非抛出异常或阻止程序流程。

  2. 后置通知(After returning advice):在目标方法成功执行之后执行的通知。可以访问目标方法的返回值,但无法修改它。

  3. 异常通知(After throwing advice):在目标方法抛出异常后执行的通知。可以访问到目标方法抛出的异常,并进行相应的处理。

  4. 最终通知(After (finally) advice):无论目标方法执行成功与否,最终通知都会在目标方法执行之后执行。

  5. 环绕通知(Around advice):包围目标方法的通知,可以在目标方法执行之前和之后执行自定义的逻辑。它最大的特点是可以完全控制目标方法的执行,包括是否执行目标方法以及如何处理返回值

以下是使用注解配置的 Spring AOP 示例代码:

1. 创建一个切面类,定义各种通知:

```java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore() {
        System.out.println("方法执行前:记录日志...");
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(Object result) {
        System.out.println("方法执行后:记录日志... 返回值为:" + result);
    }

    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "exception")
    public void logAfterThrowing(Exception exception) {
        System.out.println("方法执行出错:记录日志... 异常信息为:" + exception.getMessage());
    }

    @After("execution(* com.example.service.*.*(..))")
    public void logAfter() {
        System.out.println("方法执行后(无论成功与否):记录日志...");
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕通知:方法执行前...");
        Object result = joinPoint.proceed();
        System.out.println("环绕通知:方法执行后...");
        return result;
    }
}
```

2. 创建一个服务类:

```java
package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class MyService {

    public String doSomething() {
        System.out.println("执行业务逻辑...");
        return "业务逻辑执行完毕";
    }

    public void doSomethingWithError() throws Exception {
        System.out.println("执行业务逻辑...出现异常");
        throw new Exception("业务逻辑执行出错");
    }
}
```

3. 配置 Spring 配置文件:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.example" />
    <aop:aspectj-autoproxy />

</beans>
```

在这个示例中,切面类 `LoggingAspect` 包含了前置通知、后置通知、异常通知、最终通知和环绕通知。通过在切面类中使用 `@Before`、`@AfterReturning`、`@AfterThrowing`、`@After` 和 `@Around` 注解,来定义各种通知。然后在 `MyService` 类中使用了这些通知,它的 `doSomething()` 方法被切面类中的各种通知所包围。

配置文件中使用了 `<aop:aspectj-autoproxy />` 开启了自动代理,使得 Spring 能够识别和应用切面。

使用注解配置 Spring AOP 。使用注解配置的示例:

首先,创建一个切面类,使用 `@Aspect` 注解标注,并在方法上使用其他注解定义切点和通知:

```java
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")
    private void serviceMethods() {}

    @Before("serviceMethods()")
    public void logBefore() {
        System.out.println("方法执行前:记录日志...");
    }

    @AfterReturning("serviceMethods()")
    public void logAfterReturning() {
        System.out.println("方法执行后:记录日志...");
    }
}
```

然后,在 Spring 配置类中启用组件扫描,并使用 `@EnableAspectJAutoProxy` 注解启用 AOP:

```java
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {

}
```

接下来,在需要应用切面的业务类中,可以使用 `@Service`、`@Repository` 或 `@Component` 注解标注:

```java
package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class MyService {

    public void doSomething() {
        System.out.println("执行业务逻辑...");
    }
}
```

最后,运行时,Spring 会自动扫描并创建切面,并将它们织入到相应的组件中。当调用 `MyService` 中的 `doSomething()` 方法时,日志记录的切面将在方法执行前和执行后被调用,记录日志信息。

总结:

1.加载aop的springbean,导入spring依赖时已经被导入了

2.导入aspectj依赖

3.将共性方法抽出放到一个单独类里面

4.定义切入点: 写一个私有方法 在其上方加入 @Pointcut(“execution(void com.itheima.dao.BookDao.update())”) 注解 加 描述需要绑定的切入点方法的

5.绑定切入点和共性方法的关系 在共性方法上加入 执行前:@Before(pt())

6.将存储共性方法的类配置成bean @Component,(通知类)

7.并且加上AOP注解 @Aspect

8.在spring核心配置类上加上@EnableAspectJAutoProxy 用来启动AOP容器

相关推荐

  1. SpringAOP的实现原理

    2024-03-11 21:34:02       31 阅读
  2. 一个简易的SpringAOP实例

    2024-03-11 21:34:02       38 阅读
  3. 浅谈SpringAOP实现原理

    2024-03-11 21:34:02       20 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-11 21:34:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-11 21:34:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-11 21:34:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-11 21:34:02       20 阅读

热门阅读

  1. web蓝桥杯真题:展开你的扇子

    2024-03-11 21:34:02       19 阅读
  2. linux 环境变量

    2024-03-11 21:34:02       23 阅读
  3. Vue3:toRef和toRefs的用法

    2024-03-11 21:34:02       23 阅读
  4. 【C++】【设计模式的六大原则】

    2024-03-11 21:34:02       24 阅读
  5. 深入理解Redis:工程师的使用指南

    2024-03-11 21:34:02       20 阅读
  6. 【备忘录】docker清理指令

    2024-03-11 21:34:02       20 阅读
  7. Flutter入门学习——Flutter和Dart

    2024-03-11 21:34:02       24 阅读
  8. ms office学习记录11:Excel㈤

    2024-03-11 21:34:02       16 阅读
  9. ChatGPT消息发不出去了?我找到解决方案了

    2024-03-11 21:34:02       43 阅读