当前位置: 首页 > news >正文

Java-Spring入门指南(十一)代理模式与Spring AOP实战

Java-Spring入门指南(十一)代理模式与Spring AOP实战

  • 前言
  • 一、代理模式
    • 1.1 静态代理
      • 步骤1:定义租房接口(抽象行为)
      • 步骤2:实现房东类(真实对象)
      • 步骤3:编写中介类(代理对象)
      • 步骤4:测试静态代理
      • 静态代理的优缺点
    • 1.2 动态代理
  • 二、AOP是什么?
    • 2.1 AOP是什么?
    • 2.2 AOP有什么用?
    • 2.3 AOP的使用场景是什么?
    • 2.4 AOP的核心特点是什么?
  • 三、AOP在Spring中的应用
    • 3.1 准备依赖
    • 3.2 配置Spring的AOP命名空间
    • 3.3 定义业务接口与实现类
      • 学生服务接口(StudentService.java)
      • 学生服务实现类(StudentServiceImpl.java)
    • 3.4 定义“切面”类(增强逻辑)
    • 3.5 配置AOP:指定切入点与通知
  • 四、测试Spring AOP


前言

在前一篇博客中,我们掌握了Spring纯Java类配置的技巧,彻底摆脱了XML的束缚。

  • 而Spring中另一项核心技术——面向切面编程(AOP),能让我们在不修改原有业务代码的前提下,为方法添加额外功能(如日志、事务、权限校验等)。

我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Java-Spring入门指南知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_13040333.html?spm=1001.2014.3001.5482

在这里插入图片描述


Spring的官方AOP讲解网站
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#aop

一、代理模式

代理模式的核心是:通过“代理对象”代替“真实对象”,在不修改真实对象的前提下,为其添加额外功能

我们用房东中介租客的例子来列举一下

  • 房东(真实对象):有房子要租,但不想直接和租客打交道,还想在租房前后做额外操作(如签合同、收押金)。
  • 中介(代理对象):代替房东与租客交互,能在“租客租房”的前后添加自己的操作(如带看、收中介费)。
  • 租客(调用者):只需和中介交互,就能完成租房,无需关心房东的细节。

1.1 静态代理

静态代理需要手动为每个真实对象编写对应的代理类,步骤如下:

步骤1:定义租房接口(抽象行为)

// 租房接口:定义租房的核心行为
public interface Rent {void rentHouse(); // 租房方法
}

步骤2:实现房东类(真实对象)

// 房东:真实对象,实现租房接口
public class Landlord implements Rent {@Overridepublic void rentHouse() {System.out.println("房东:我的房子成功租出去了");}
}

步骤3:编写中介类(代理对象)

// 中介:代理对象,也实现租房接口
public class Mediator implements Rent {private Landlord landlord; // 持有真实对象(房东)的引用public Mediator(Landlord landlord) {this.landlord = landlord;}@Overridepublic void rentHouse() {// 租房前:中介的额外操作System.out.println("中介:带租客看房,收取中介费");// 调用真实对象的核心方法landlord.rentHouse();// 租房后:中介的额外操作System.out.println("中介:协助签合同,收取押金");}
}

步骤4:测试静态代理


public class ProxyTest {public static void main(String[] args) {// 1. 创建真实对象(房东)Landlord landlord = new Landlord();// 2. 创建代理对象(中介),并传入房东Mediator mediator = new Mediator(landlord);// 3. 通过中介租房(调用代理对象的方法)mediator.rentHouse();}
}

运行结果:
在这里插入图片描述

静态代理的优缺点

  • 优点:逻辑直观,能在不修改真实对象的前提下,为其添加额外功能。
  • 缺点:代理类与真实对象绑定,若有100个真实对象,就得写100个代理类,代码冗余且维护成本高。

1.2 动态代理

动态代理无需手动编写代理类,而是运行时自动生成代理对象(常见的有JDK动态代理——基于接口、CGLIB动态代理——基于子类)。

但动态代理的底层代码较为复杂,而Spring AOP帮我们封装了这些细节,让我们能更简单地使用AOP。


二、AOP是什么?

静态代理的“一对一”绑定方式,在复杂业务中会变得非常繁琐。而AOP(Aspect Oriented Programming,面向切面编程) 正是为解决这个问题而生:它能通过“切面”,对多个类的多个方法 统一添加增强功能,完全无需手动编写代理类。

2.1 AOP是什么?

AOP是一种编程思想,核心逻辑是:将与核心业务无关,但又分散在多个业务中的通用功能(如日志、事务、权限),抽取成“切面(Aspect)”,在合适的时机(如方法执行前/后),动态“织入”到业务方法中

在这里插入图片描述

简单来说:业务代码只关注核心逻辑,通用功能交给AOP统一处理

2.2 AOP有什么用?

AOP专为解决“横切关注点”问题而生:

  • 横切关注点:与业务逻辑无关,但需在多个业务方法中重复出现的逻辑(如日志打印、事务控制、异常处理、权限校验等)。
  • AOP的价值:让横切关注点与业务逻辑解耦,只需写一次,就能作用于多个方法,既减少代码冗余,又便于统一维护。

2.3 AOP的使用场景是什么?

AOP的典型应用场景包括:

  • 日志记录:方法执行前/后自动记录日志。
  • 事务管理:方法执行前开启事务,执行后提交/回滚事务。
  • 权限校验:方法执行前校验用户权限。
  • 性能监控:统计方法的执行时间。
  • 异常处理:统一捕获和处理方法中的异常。

2.4 AOP的核心特点是什么?

  • 切面(Aspect):横切关注点的封装(如“日志切面类”),包含“何时增强”“增强哪些方法”“做什么增强”。
  • 通知(Advice):切面中的具体增强逻辑(如“方法执行前打印日志”),分为前置通知(before)、后置通知(after)、环绕通知(around)等。
  • 连接点(Join Point):程序中可以被增强的点(Spring AOP中主要指方法调用)。
  • 切入点(Pointcut)具体要增强的连接点,通过表达式指定(如“增强com.niit包下所有Service的方法”)。
  • 织入(Weaving):将切面的通知“织入”到目标方法的过程(Spring在运行时完成织入)。

三、AOP在Spring中的应用

Spring对AOP提供了完善的支持,我们可以通过XML配置或注解实现AOP。下面结合代码,用XML配置方式实战Spring AOP。

3.1 准备依赖

使用Spring AOP需添加aspectjweaver依赖:

<!-- AspectJ织入依赖:支持AOP功能的核心依赖 -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.9.1</version>
</dependency>

在这里插入图片描述

3.2 配置Spring的AOP命名空间

applicationContext.xml中,添加AOP的命名空间和约束:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 组件扫描:让Spring管理带@Service/@Component等注解的类 --><context:component-scan base-package="org.example.aop1"/>
</beans>

3.3 定义业务接口与实现类

定义接口和实现类:

学生服务接口(StudentService.java)

public interface StudentService {void add();   // 添加学生void del();   // 删除学生void update();// 修改学生void query(); // 查询学生
}

学生服务实现类(StudentServiceImpl.java)


import org.springframework.stereotype.Component;// 注册为Spring的Bean,id为"ssi"
@Component("ssi")
public class StudentServiceImpl implements StudentService {@Overridepublic void add() {System.out.println("【核心业务】添加学生");}@Overridepublic void del() {System.out.println("【核心业务】删除学生");}@Overridepublic void update() {System.out.println("【核心业务】修改学生");}@Overridepublic void query() {System.out.println("【核心业务】查询学生");}
}

在这里插入图片描述

3.4 定义“切面”类(增强逻辑)

创建“日志切面”,在方法执行前打印增强信息:


import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;// 注册为Spring的Bean
@Component
public class LogBefore implements MethodBeforeAdvice {/*** 方法执行前的增强逻辑* @param method 被增强的方法* @param args 方法参数* @param target 被增强的目标对象*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("【AOP增强】" + "类:" + target.getClass().getName() + ",方法:" + method.getName() + " 即将执行~");}
}

3.5 配置AOP:指定切入点与通知

applicationContext.xml中,配置“哪些方法”要被“哪个切面”增强:

<!-- AOP配置:将增强逻辑织入目标方法 -->
<aop:config><!-- 1. 定义切入点:通过表达式指定要增强的方法 --><!-- execution(* com.niit.aop1.*.*(..)) 含义:- 第一个*:返回值类型任意- com.niit.aop1.*:com.niit.aop1包下的任意类- 第二个*:类中的任意方法- (..):方法参数任意(个数、类型不限)--><aop:pointcut id="myPointcut" expression="execution(* org.example.aop1(..))"/><!-- 2. 配置通知:将LogBefore的增强逻辑,织入到myPointcut指定的方法中 --><aop:advisor advice-ref="logBefore" pointcut-ref="myPointcut"/>
</aop:config>

在这里插入图片描述

配置说明:

  • aop:pointcut:通过expression表达式定义切入点(要增强的方法)。
  • aop:advisor:将通知advice-ref指定的LogBefore)与切入点pointcut-ref指定的myPointcut)关联,完成“织入”。

四、测试Spring AOP

编写测试类,获取StudentService的Bean并调用方法,观察AOP是否生效:

import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {public static void main(String[] args) {// 加载Spring配置文件ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");// 获取StudentService的Bean(注意:此时获取的是Spring生成的代理对象)StudentService studentService = (StudentService) context.getBean("ssi");// 调用方法,触发AOP增强studentService.add();studentService.query();// 关闭容器context.close();}
}

运行结果:
在这里插入图片描述

可以看到:无需修改StudentServiceImpl的代码,方法执行前自动添加了日志增强逻辑——这就是AOP的“无侵入式增强”魅力。


我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Java-Spring入门指南知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_13040333.html?spm=1001.2014.3001.5482

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

http://www.dtcms.com/a/422451.html

相关文章:

  • 实名认证接口-识破虚假身份:科技为信任筑起第一道防线
  • 柘林网站建设wordpress改背景图片
  • RokcetMQ事务消息详解
  • Athena + S3 数据分析实战(深度版):从数据湖到可视化 BI
  • IP纯净度检测工具
  • 第四部分:VTK常用类详解(第114章 vtkStreamTracer流线追踪类)
  • MATLAB的CFAR(恒虚警率)图像目标检测
  • 2025三掌柜赠书活动第三十五期 AI辅助React Web应用开发实践:基于React 19和GitHub Copilot
  • HRPC在Polaris存储系统中的应用
  • 网站在百度无法验证码怎么办网站开发技术有包括
  • 【AI时代速通QT】第八节:Visual Studio与Qt-从项目迁移到多版本管理
  • Spring线程池:ThreadPoolExecutor与ThreadPoolTaskExecutor终极对比
  • IDEA创建SpringBoot项目使用JDK1.8
  • 深入分析JAR和WAR包的区别 (指南七)
  • 详解 OpenCV 中的仿射变换:原理与实战案例
  • 计算机视觉(opencv)——基于 dlib 和 CNN卷积神经网络 的人脸检测
  • 黑色背景的网站开发工具微信商城收费吗
  • html快速学习
  • 门户网站 模板之家办公室门户网站建设和管理工作
  • Git 基础 - 查看提交历史
  • 《Linux 构建工具核心:make 命令、进度条、Gitee》
  • vlan batch { vlan-id1 [ to vlan-id2 ] } 概念及题目
  • 济宁网站建设服务互联网公司怎么赚钱
  • Linux-简单命令
  • Linux ​​ls​​ 命令进阶:从隐藏文件到递归显示,成为文件浏览大师
  • VPS服务器锁等待超时处理,如何有效解决数据库性能瓶颈
  • 英伟达服务器维修市场崛起:捷智算GPU维修中心的技术突围之路
  • 第四部分:VTK常用类详解(第102章 vtkButtonWidget按钮控件类)
  • 进阶02:Labview操作者框架
  • 3.0 labview使用SQLServer