likes
comments
collection
share

面向切面编程

作者站长头像
站长
· 阅读数 10

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

什么是面向切面编程

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

这很抽象。

我们换种理解~

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

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

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

AOP 中的概念

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

案例图解

未使用 AOP

面向切面编程

使用 AOP

面向切面编程

简单案例

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

添加 aspect 依赖:

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

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

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 注解:

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

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 的类进行测试:

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 实战派》