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

Spring Ioc和Aop,Aop的原理和实现案例,JoinPoint,@Aspect,@Before,@AfterReturning

DAY25.2 Java核心基础

Spring两大核心:Ioc和Aop

IOC

Ioc容器:装载bean的容器,自动创建bean

三种方式:

1、基于xml配置:通过在xml里面配置bean,然后通过反射机制创建bean,存入进Ioc容器中

2、基于注解的方式:通过注解标记类,Ioc读取有相关注解的类,然后通过反射创建bean对象存入Ioc容器中

3、基于配置类的方式:写一个java文件来替代xml,通过@Bean注解标记需要创建的对象,通过反射创建存入Ioc容器中

AOP

AOP:Aspect Oriented Programming,面向切面编程

面向对象编程 OOP (Object Oriented Programming):将程序中所有参与模块都抽象成对象,通过对象之间的相互调用关系来完成业务需求。

AOP:指的是把切面抽象为对象,在程序运行的时候动态的将非业务代码(比如打印日志)切入到业务代码中,从而实现代码的解耦合,将非业务代码抽象为一个对象

AOP优点:

  • 实现代码的解耦合
  • 提高代码的复用性
  • 提高代码的可维护性
  • 集中式管理横切逻辑
  • 提升开发效率
  • 业务代码不受非业务代码的影响,逻辑更加清晰
应用场景说明
日志记录自动打印请求参数、响应、耗时等
权限验证判断用户是否有权限执行操作
事务管理保证一组数据库操作的原子性
性能监控记录方法执行时间、内存等
异常处理统一捕获、记录、响应异常信息
缓存控制方法调用前先查缓存,结果缓存

总结一句话:AOP 本质上是“增强”代码的能力,不修改原代码,也能插入额外逻辑,让系统更模块化、更灵活、更清晰。

案例示例:

创建一个计算的接口

CalService:

public interface CalService {int add(int a, int b);int sub(int a, int b);int mul(int a, int b);int div(int a, int b);
}

实现类CalServiceImpl

@Component("calService")
public class CalServiceImpl implements CalService{@Overridepublic int add(int num1, int num2) {int result = num1 + num2;return result;}@Overridepublic int sub(int num1, int num2) {int result = num1 - num2;return result;}@Overridepublic int mul(int num1, int num2) {int result = num1 * num2;return result;}@Overridepublic int div(int num1, int num2) {int result = num1 / num2;return result;}
}

测试方法

public static void main(String[] args) {AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("org.nanfengspringboot01.aop");CalService calService = (CalService) annotationConfigApplicationContext.getBean("calService");System.out.println(calService.add(4, 2));System.out.println(calService.sub(4, 2));System.out.println(calService.mul(4, 2));System.out.println(calService.div(4, 2));
}

输出:

image-20250522145926561

如果我们需要记录打印日志的话,是不是要更改实现类文件的实现

@Component("calService")
public class CalServiceImpl implements CalService{@Overridepublic int add(int num1, int num2) {System.out.println("执行了加法运算");int result = num1 + num2;System.out.println("结果是:" + result);return result;}@Overridepublic int sub(int num1, int num2) {System.out.println("执行了减法运算");int result = num1 - num2;System.out.println("结果是:" + result);return result;}@Overridepublic int mul(int num1, int num2) {System.out.println("执行了乘法运算");int result = num1 * num2;System.out.println("结果是:" + result);return result;}@Overridepublic int div(int num1, int num2) {System.out.println("执行了除法运算");int result = num1 / num2;System.out.println("结果是:" + result);return result;}
}

但是这样写的代码耦合程度太高了

咱可以用AOP来实现切面编程,将打印日志作为一个切面类抽象出来

创建切面类CalAop

@Aspect
@Component
public class CalAop {@Before("execution(public int org.nanfengspringboot01.aop.CalService.*(..))")public void before(JoinPoint joinPoint) {System.out.println("Aop切面进入@before");System.out.println("方法名:" + joinPoint.getSignature().getName());Object[] args = joinPoint.getArgs();String string = Arrays.toString(args);System.out.println("方法参数:"+string);}@AfterReturning(value = "execution(public int org.nanfengspringboot01.aop.CalService.*(..))", returning = "result")public void after(JoinPoint joinPoint,Object result) {System.out.println("Aop切面进入@AfterReturning");String methodName = joinPoint.getSignature().getName();System.out.println(methodName+"方法结果是:"+result);System.out.println("Aop切面结束");System.out.println("----------------------------------");}
}

@Aspect:标记这个类为切面类

@Component:标记这个类需要注入到Ioc容器中

@Before:定义切面的位置,在方法执行之前执行

@AfterReturning/@After:定义切面的位置,在方法执行之后执行

JoinPoint 是 Spring AOP(面向切面编程)中的一个核心接口,它代表了在程序执行过程中可以插入横切关注点(如日志、事务、安全等)的一个具体“连接点”(比如方法调用或异常抛出)。

获取当前连接点的信息

  • 可以获取正在被拦截的方法、参数、目标对象等信息。

  • 常见用途:记录日志、权限校验、参数处理等。

支持在切面中访问原始方法的上下文

  • 例如方法名、参数值、注解等,便于做统一处理。

配合 @Around, @Before, @AfterReturning 等注解使用

  • 在定义切面方法时,作为参数传入,用于操作目标方法或获取其执行上下文。
AOP 为什么要使用接口,不直接使用类

AOP 底层实现用的是jdk动态代理,动态创建一个类,创建对象,关于动态代理可以查看我之前的动态代理文章

怎么动态创建类?依据:接口

AOP 是基于 IoC 容器的

使用 IoC 容器创建所有的 bean,再进行整合

有了切面类实现类就不需要打印那么多的日志了

@Component("calService")
public class CalServiceImpl implements CalService{@Overridepublic int add(int num1, int num2) {int result = num1 + num2;return result;}@Overridepublic int sub(int num1, int num2) {int result = num1 - num2;return result;}@Overridepublic int mul(int num1, int num2) {int result = num1 * num2;return result;}@Overridepublic int div(int num1, int num2) {int result = num1 / num2;return result;}
}

测试启动类:

@SpringBootApplication
//@EnableAspectJAutoProxy
@MapperScan("org.nanfengspringboot01.mapper")
public class Nanfengspringboot01Application {public static void main(String[] args) {ConfigurableApplicationContext ioc = SpringApplication.run(Nanfengspringboot01Application.class, args);CalService calService = (CalService) ioc.getBean("calService");calService.add(4,2);calService.sub(4,2);calService.mul(4,2);calService.div(4,2);}}

SpringApplication.run(Nanfengspringboot01Application.class, args)的结果就是上下文的ioc容器,可以根据这个获取到所有的bean信息,也可以获取到对应的bean对象

@EnableAspectJAutoProxy注解在新版本是不用加的,springboot会自动整合

输出:

image-20250522151847199

http://www.xdnf.cn/news/594865.html

相关文章:

  • 如何使用小爱音响控制海尔等第三方平台设备
  • 从实验室到产业化:探究FSHD 技术发展史如何重塑显示行业格局?
  • 【物理学】声子:凝聚态物理中的关键概念
  • 视觉理解多模态模型转为API服务
  • 【Hexo】1.搭建本地初始默认的博客
  • 链表day4
  • 多线程初阶(3)
  • 数据表格控件TeeGrid for VCL/FMX:让数据“说话”更直观!
  • Android滑动冲突解决方法
  • 西交交互增强与细节引导的具身导航!OIKG:基于观察图交互与关键细节融合框架下的视觉语言导航
  • unittest
  • GITLIbCICD流水线搭建
  • 【Java高阶面经:数据库篇】17、分库分表分页查询优化:告别慢查询与内存爆炸
  • 软件设计师“设计原则”真题考点分析——求三连
  • [Usaco2007 Dec]队列变换 题解
  • AUTOSAR图解==>AUTOSAR_SRS_PortDriver
  • 硅基计划2.0 学习总结 叁
  • CLIP中的被动学习
  • OpenAI宣布:核心API支持MCP,助力智能体开发
  • memcpy 函数的使用 (C语言)
  • 110kV/630mm2电缆5km的交流耐压试验兼顾110kVGIS开关用
  • 彩礼的异化:婚姻市场中的资本规训与性别政治批判
  • NV013NV024美光固态闪存NV028NV034
  • Tomcat多实例配置
  • 从零开始学习QT——第一步
  • vue组件渲染到iframe里面(同域名下),组件可以在同一项目下维护
  • VPC的作用
  • python调wfdb库读欧洲st-t数据库
  • 让办公更聪明:OA系统如何重塑企业协作模式
  • 第六部分:第五节 - 数据持久化 (基础):管理厨房的原材料库存