📜  Spring Boot – AOP 和 OOP 的区别(1)

📅  最后修改于: 2023-12-03 15:05:15.767000             🧑  作者: Mango

Spring Boot – AOP 和 OOP 的区别

介绍

在面向对象编程(OOP)中,我们主要关注对象的行为和特性,采用一种基于类的封装方式来组织代码,每个类都包含了一组属性和方法,方法是类的行为,属性是类的数据。

而在面向切面编程(AOP)中,我们主要关注横切关注点(cross-cutting concerns),如日志、事务管理、安全等,这些关注点可能分布在多个类或对象中,通过切面的概念来对其进行统一管理,切面可以看作是对类或对象的某些方法进行增强,而不是修改它们的代码。这样可以让我们更加专注于核心业务逻辑,而不用担心这些横切关注点会给我们的代码带来复杂度和重复性的问题。

本篇文章将重点介绍 Spring Boot 中 AOP 和 OOP 之间的区别,以及如何使用 Spring Boot AOP 来实现切面编程。

AOP 和 OOP 的区别
  • OOP 面向对象编程,AOP 面向切面编程,都是编程范式的概念。
  • OOP 更加关注对象间的相互关系和封装,AOP 更加关注横向的关注点的代码重用和解耦。
  • OOP 的抽象级别更加高,AOP 更加注重实现细节。
  • OOP 的代码基于类和对象,而 AOP 的代码则是基于切面和通知。
Spring Boot AOP 基础

Spring Boot 提供了 AOP 的支持,通过使用 Spring AOP 模块和 AspectJ 工具,可以方便地实现对 Java 方法的切面编程。下面我们来看一下 Spring Boot AOP 的基本概念和使用方式。

Join Point

Join Point 是指程序执行过程中的一个步骤,比如方法调用、异常抛出等等,这些步骤都可以被切面拦截并进行增强。Spring Boot AOP 支持以下五种 Join Point:

  • Method execution:方法执行。
  • Constructor execution:构造器执行。
  • Field access:字段访问。
  • Field modification:字段修改。
  • Exception handling:异常处理。
Pointcut

Pointcut 是一个表达式,用于指定切面的 Join Point,只有匹配到 Pointcut 的 Join Point 才会被切面拦截并进行增强。

Pointcut 表达式的语法比较复杂,主要包括以下几种类型:

  • execution:用于匹配方法,如 execution(* com.example.service.*.*(..)) 表示匹配 com.example.service 包中所有类的所有方法。
  • within:用于匹配类,如 within(com.example.service.*) 表示匹配 com.example.service 包中所有类。
  • this:用于匹配当前对象,如 this(com.example.service.FooService) 表示匹配当前对象为 FooService 类型的执行方法。
  • target:用于匹配目标对象,如 target(com.example.service.FooService) 表示匹配目标对象为 FooService 类型的执行方法。
  • args:用于匹配参数,如 args(String, ..) 表示匹配第一个参数为 String 类型的执行方法。
  • @annotation:用于匹配方法上的注解,如 @annotation(org.springframework.transaction.annotation.Transactional) 表示匹配所有使用 @Transactional 注解的方法。
Advice

Advice 是切面在 Join Point 上执行的动作,包括 Before、After、Around、AfterReturning、AfterThrowing 等几种类型。

  • Before:在 Join Point 执行前执行。
  • After:在 Join Point 执行后执行,无论 Join Point 是否抛出异常。
  • Around:在 Join Point 执行前后都执行,可以控制是否调用原始 Join Point。
  • AfterReturning:在 Join Point 执行后执行,只有在 Join Point 正常返回时才会执行。
  • AfterThrowing:在 Join Point 执行过程中抛出异常时执行。
Aspect

Aspect 是一个类,包含了一组 Pointcut 和 Advice,用于增强特定的 Join Point,比如打印日志、参数验证等。

使用示例

下面通过一个简单的例子来说明如何在 Spring Boot 中使用 AOP:

定义一个切面类,实现了 Before 和 AfterReturning 两种 Advice:

@Aspect
@Component
public class UserServiceAspect {
    @Before("execution(* com.example.service.UserService.addUser(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("Before addUser method...");
    }
    @AfterReturning("execution(* com.example.service.UserService.addUser(..))")
    public void afterReturningAdvice(JoinPoint joinPoint) {
        System.out.println("After addUser method...");
    }
}

定义一个 UserService 接口和实现类:

public interface UserService {
    void addUser(String username, String password);
}

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void addUser(String username, String password) {
        System.out.println("Adding user: " + username);
    }
}

在启动类中添加 @EnableAspectJAutoProxy 注解,并手动注册切面类:

@SpringBootApplication
@EnableAspectJAutoProxy
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    @Bean
    public UserServiceAspect userServiceAspect() {
        return new UserServiceAspect();
    }
}

执行 addUser 方法:

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/addUser")
    public void addUser() {
        userService.addUser("admin", "123456");
    }
}

访问 http://localhost:8080/addUser,控制台输出:

Before addUser method...
Adding user: admin
After addUser method...

可以看到 Before 和 AfterReturning 两种 Advice 成功地对 addUser 方法进行了增强。

小结

本篇文章介绍了 Spring Boot 中 AOP 和 OOP 之间的区别,以及如何在 Spring Boot 中使用 AOP 实现切面编程。通过 AOP,我们可以方便地对代码中的横切关注点进行统一管理,提高代码的可重用性和可维护性。