第21~22周Java主流框架入门-Spring 2.SpringAOP面向切面编程

1.Spring AOP (Aspect-Oriented Programming)


1. 1. 什么是 Spring AOP?

  • AOP(面向切面编程) 是 Spring 提供的一种可插拔的组件技术,允许我们在软件运行过程中添加额外的功能。
  • 场景:假设有两个模块,用户管理模块A和员工管理模块B。现在需要在业务处理过程中添加权限过滤功能。
    • 如果在两个模块中都添加权限判断代码,当权限需求变化时,需要再次修改代码,这样会增加开发和维护成本。
    • 使用 Spring AOP,我们可以将权限判断的代码独立为一个切面,在代码执行前进行权限过滤,而不需要修改原业务逻辑。

1. 2. 面向切面编程 (AOP) 的核心概念

  • 切面(Aspect):表示横切的功能模块,用于实现某些通用功能(如权限检查、日志记录等)。切面可以在方法执行前后插入。
  • 权限切面:在执行业务逻辑之前判断用户权限。
  • 日志切面:记录业务逻辑的执行时间、输入参数、输出结果等信息。
    • 通过切面技术,日志和权限判断代码可以在不修改业务代码的情况下被“织入”程序。
    • 如果业务需求发生变化,只需调整配置即可轻松移除切面,不影响核心业务逻辑。

1. 3. 切面与插件技术的类比

  • 切面类似于我们在浏览器中安装的插件,可以为现有的业务模块增加额外的功能。
    • 例如:安装翻译插件后,浏览器可以将英文网页自动翻译为中文。
    • 一旦不需要这些功能,卸载插件即可,还原浏览器的原始状态。
    • 切面也是如此,它为业务模块提供了额外的功能,但这些模块本身不会感知到切面的存在。

1. 4. 为什么叫“切面”?

  • 正常的软件执行流程是从上到下按照代码顺序执行的,而切面则像一个横切面,在执行过程中横插进入业务流程中。
    • 这些横切的功能模块就是所谓的“切面(Aspect)”,通过切面我们可以为现有的业务逻辑增加扩展功能。

1. 5. AOP 的最终目的

  • 不修改源码 的情况下扩展程序行为。
  • 通常将与业务无关的通用功能(如权限检查、日志记录)封装为切面类,通过配置来插入这些功能。
  • 切面可以配置在目标方法的执行前、执行后,达到真正的“即插即用”。

2.Spring AOP - 实战配置项目

课程简介

本节课程将通过实际项目配置,带领大家一步一步理解 Spring AOP(面向切面编程)的功能。我们将基于 XML 配置的形式来实现 AOP,并通过演示了解 AOP 如何对现有系统进行功能扩展,而无需修改源代码。


2. 1. 项目结构介绍

  • 本次演示基于 s01 工程,其中包含了两个主要部分:
    • DAO 层:包括 EmployeeDaoUserDao,分别用于对员工表和用户表的数据增删改查。
    • Service 层:包括 EmployeeServiceUserService,分别提供了员工相关的业务逻辑和用户管理的业务逻辑。
      • EmployeeService:提供 entry 方法,模拟员工入职操作。
      • UserService:提供 createUser 方法(创建用户)和 generateRandomPassword 方法(生成随机密码)。

这些类的业务逻辑非常常规,但本节课我们将通过 AOP 实现对方法执行时间的监控,解决手动添加代码带来的冗余和复杂度问题。


2. 2. 需求描述

我们希望在系统运行过程中,对所有 Service 层和 DAO 层的方法调用前打印执行时间,从而便于分析系统负载高峰时间。

问题:

  • 如果直接在每个方法中手动添加 System.out.println() 代码,维护和删除这些代码将变得非常麻烦。
  • AOP 可以在不修改原代码的情况下,灵活地添加或移除这些功能。

2. 3. 配置项目依赖

首先,我们需要在 pom.xml 文件中添加必要的依赖项:

<dependencies>
    <!-- Spring context dependency -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    
    <!-- AspectJ Weaver (AOP 底层依赖) -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.5</version>
    </dependency>
</dependencies>

spring-context 是用来初始化 IOC 容器的基础依赖,而 aspectjweaver 则是 AOP 的底层依赖,负责切面功能的实现。


2. 4. 配置 applicationContext.xml

接下来,我们需要在 resources 目录下创建 applicationContext.xml 文件,这是 Spring IOC 的配置文件。

添加命名空间:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置 Beans -->
    <bean id="userDao" class="com.example.dao.UserDao" />
    <bean id="employeeDao" class="com.example.dao.EmployeeDao" />
    
    <bean id="userService" class="com.example.service.UserService">
        <property name="userDao" ref="userDao" />
    </bean>
    
    <bean id="employeeService" class="com.example.service.EmployeeService">
        <property name="employeeDao" ref="employeeDao" />
    </bean>
</beans>

引入 aop 命名空间:

该命名空间用于配置 AOP 所需的相关标签。它将帮助我们在不修改源代码的前提下,为现有方法添加执行时间打印功能。


2. 5. 初始化 IOC 容器并执行测试

接下来,我们在 aop 包下创建一个 Spring 应用的入口类:

public class SpringApplication {
   
    public static void main(String[] args) {
   
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        UserService userService = context.getBean("userService", UserService.class);
        userService.createUser();  // 模拟创建用户的过程
    }
}

运行代码后,可以看到控制台输出显示了 UserServiceUserDao 中各个方法的执行情况。


2. 6. Spring AOP - 方法执行时间打印需求实现

课程目标

通过 AOP 实现对 ServiceDAO 层中任意方法的执行时间进行打印,并避免在每个方法中手动增加日志打印代码。AOP 能够灵活地实现这些功能,且无需修改源代码。


1. 新增切面类 (Method Aspect)

在 AOP 配置中,我们需要创建一个切面类,用于扩展业务逻辑。在 aop 包下新增一个 aspect 包,创建切面类 MethodAspect,用于打印方法的执行时间。

切面类 MethodAspect

public class MethodAspect {
   
    public void printExecutionTime(JoinPoint joinPoint) {
   
        // 获取当前时间并格式化
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String now = sdf.format(new Date
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值