面向切面编程

本文,我们来谈谈面向切面编程。

什么是面向切面编程

面向切面编程(Aspect Oriented Program, 简称 AOP)是一种编程范式,用于解藕系统中的横切关注点。

这很抽象。

我们换种理解~

面向切面编程把业务功能分为核心、非核心两部分。比如:

  • 核心业务功能:用户登陆、增加数据、删除数据
  • 非核心业务功能:性能统计、日志、事务管理

Spring 的面向编程思想中,非核心业务功能被定义为切面 。核心业务功能和切面功能(非核心功能)被分别进行独立开发,然后把切面功能和核心业务功能编织 在一起,这就是 AOP

AOP 中的概念

术语 解析
切入点 pointcut 在哪些类、哪些方法上切入
通知 advice 在方法前、方法后、方法前后做了什么
切面 aspect 切面 = 切入点 + 通知
织入 weaving 把切面加入对象,并创建出代理对象的过程
环绕通知 AOP 中最强大、灵活的通知,它集成了前置和后置通知,保留了连接点原有的方法

案例图解

未使用 AOP

使用 AOP

简单案例

假设我们开发一个简单用户管理系统。

添加 aspect 依赖:

xml 复制代码
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
</dependency>

我们创建一个切面类,定义了我们要应用的横切关注点

java 复制代码
package com.launch;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.launch.UserService.addUser(..))")
    public void logBeforeAddUser() {
        System.out.println("Before adding a user...");
    }

    @Before("execution(* com.launch.UserService.deleteUser(..))")
    public void logBeforeDeleteUser() {
        System.out.println("Before deleting a user...");
    }
}

我们创建了名为 LoggingAspect 的切面类,并使用 @Before 注释定义了两个通知方法。这两个通知分别在执行 com.example.UserService.addUser()com.example.UserService.deleteUser() 方法之前打印日志。

接下来,我们创建名为 UserService 类,并添加 @Service 注解:

java 复制代码
package com.launch;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void addUser(String username) {
        // add logic
        System.out.println("add logic " + username);
    }
    public void deleteUser(String username) {
        // remove logic
        System.out.println("delete logic " + username);
    }
}

然后我们在程序入口文件中添加 @EnableAspectJAutoProxy 注解,以启用 AOP

java 复制代码
package com.launch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class LaunchApplication {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(LaunchApplication.class);
        app.run(args);
    }

}

然后我们创建名为 JimmyController 的类进行测试:

java 复制代码
package com.launch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class JimmyController {
    @Autowired
    private UserService userService;

    @RequestMapping("/add_and_delete")
    public String addUser() {
        userService.addUser("Jimmy");
        userService.deleteUser("Jimmy");
        return "Add Jimmy.";
    }
}

这里我们触发 Get 请求 http://localhost:8080/add_and_delete 接口就可以看到下面的结果:

参考

  • 《Spring Boot 实战派》
相关推荐
用户4001883093714 分钟前
手搓本地 RAG:我用 Python 和 Spring Boot 给 AI 装上了“实时代码监控”
后端
用户34140819912516 分钟前
/dev/binder 详解
后端
用户57573033462419 分钟前
🌟 从一行 HTML 到屏幕像素:浏览器是如何“画”出网页的?
前端
NEXT0622 分钟前
React Hooks 进阶:useState与useEffect的深度理解
前端·javascript·react.js
Gopher_HBo25 分钟前
Go进阶之recover
后端
sure28227 分钟前
React Native应用中使用sqlite数据库以及音乐应用中的实际应用
前端·react native
CHU72903528 分钟前
扭蛋机盲盒小程序前端功能设计解析:打造趣味与惊喜并存的消费体验
前端·小程序
专注VB编程开发20年29 分钟前
vb.net datatable新增数据时改用数组缓存
java·linux·windows
程序员布吉岛29 分钟前
写了 10 年 MyBatis,一直以为“去 XML”=写注解,直到看到了这个项目
后端
却尘29 分钟前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go