Spring 框架基础:IOC 与 AOP 原理剖析及面试要点

在上一篇中,我们深入探讨了 Java 反射机制,了解了它在运行时动态操作类和对象的强大能力。而今天,我们将进入 Spring 框架的世界。Spring 框架作为 Java 企业级开发中最流行的框架之一,极大地简化了企业级应用的开发过程。对于春招面试而言,Spring 框架的基础知识是重点考察内容,其中控制反转(IOC)和面向切面编程(AOP)是 Spring 框架的核心思想,下面我们来详细了解。

一、控制反转(IOC)

概念与原理

IOC,即控制反转(Inversion of Control),是一种设计思想,它将对象的创建和管理控制权从应用程序本身转移到了 Spring 容器中。在传统的 Java 开发中,对象的创建和依赖关系的管理由开发者在代码中手动完成,这使得代码的耦合度较高,可维护性和可测试性较差。而在 Spring 框架中,通过 IOC 容器,开发者只需将对象的定义和依赖关系配置在 XML 文件或使用注解的方式告诉 Spring 容器,由容器负责创建对象并管理它们之间的依赖关系。

IOC 的实现主要依赖于依赖注入(Dependency Injection,DI)。依赖注入是 IOC 的一种具体实现方式,它有三种常见的注入方式:构造函数注入、Setter 方法注入和接口注入(较少使用)。以构造函数注入为例:

public class UserService {private UserDao userDao;// 构造函数注入public UserService(UserDao userDao) {this.userDao = userDao;}public void saveUser() {userDao.save();}
}public interface UserDao {void save();
}public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("保存用户到数据库");}
}

在 Spring 配置文件(XML)中可以这样配置:

<bean id="userDao" class="com.example.dao.UserDaoImpl"/>
<bean id="userService" class="com.example.service.UserService"><constructor-arg ref="userDao"/>
</bean>

这样,Spring 容器在创建userService对象时,会自动将userDao对象通过构造函数注入进去。

面试题 1:IOC 的优点是什么?

答案

  • 降低耦合度:对象之间的依赖关系由 Spring 容器管理,对象无需关心其依赖对象的创建和实现细节,只需要关注自身的业务逻辑,从而降低了代码的耦合度,提高了代码的可维护性和可扩展性。例如,当UserDao的实现类发生变化时,只需要在 Spring 配置文件中修改userDao的class属性,而UserService类的代码无需修改。
  • 提高可测试性:由于对象的依赖关系可以通过外部配置进行注入,在测试时可以很方便地为对象提供模拟的依赖对象,从而提高了代码的可测试性。比如在测试UserService时,可以创建一个模拟的UserDao实现类,通过 Spring 容器注入到UserService中,方便对UserService的业务逻辑进行单独测试。
  • 方便管理和维护:Spring 容器集中管理对象的创建和生命周期,便于对对象进行统一的管理和维护,如对象的初始化、销毁等操作都可以由 Spring 容器进行控制。

面试题 2:说说 IOC 容器的工作流程?

答案

  • 资源定位:Spring 容器首先会根据配置文件的位置(如 XML 文件路径或基于注解的配置类)来定位资源。如果是 XML 配置,会读取 XML 文件;如果是基于注解的配置,会扫描指定的包路径来查找被注解标记的类。
  • BeanDefinition 载入:将配置文件中的信息解析成BeanDefinition对象,BeanDefinition包含了创建 Bean 所需的各种信息,如类名、构造函数参数、属性值、依赖关系等。
  • BeanDefinition 注册:将解析后的BeanDefinition注册到BeanDefinitionRegistry中,BeanDefinitionRegistry是 Spring 容器中用于管理BeanDefinition的核心接口,它负责维护所有已注册的BeanDefinition。
  • Bean 实例化:Spring 容器根据BeanDefinition中的信息,通过反射机制创建 Bean 实例。在实例化过程中,如果 Bean 有依赖关系,会递归地实例化其依赖的 Bean,并将它们注入到当前 Bean 中。例如,在创建userService时,会先创建userDao并注入到userService中。
  • Bean 初始化:在 Bean 实例化后,Spring 会对 Bean 进行初始化操作,如调用 Bean 的初始化方法(可以通过init-method属性指定),以及对 Bean 进行一些后置处理(如 AOP 代理的创建等)。
  • Bean 使用:完成初始化后,Bean 就可以被应用程序使用了。当应用程序需要获取某个 Bean 时,从 Spring 容器中获取即可。
  • Bean 销毁:当 Spring 容器关闭时,会对 Bean 进行销毁操作,如调用 Bean 的销毁方法(可以通过destroy-method属性指定),释放 Bean 占用的资源。

二、面向切面编程(AOP)

概念与原理

AOP,即面向切面编程(Aspect - Oriented Programming),它是一种编程范式,旨在将横切关注点(如日志记录、事务管理、权限控制等)从业务逻辑中分离出来,以提高代码的模块化和可维护性。在 Spring 框架中,AOP 通过代理模式实现,主要有 JDK 动态代理和 CGLIB 代理两种方式。

在 AOP 中,有几个关键概念:

  • 切面(Aspect):一个切面是横切关注点的模块化,它包含了一组通知和切入点的定义。例如,一个用于日志记录的切面,包含了在方法执行前后记录日志的通知以及定义哪些方法需要被记录日志的切入点。
  • 通知(Advice):通知是切面在某个连接点上执行的操作,包括前置通知(Before Advice)、后置通知(After Advice)、环绕通知(Around Advice)、异常通知(After - throwing Advice)和最终通知(After - returning Advice)。比如前置通知在方法执行前执行,可用于权限检查;环绕通知可以在方法执行前后都执行自定义逻辑,常用于事务管理。
  • 连接点(Joinpoint):连接点是程序执行过程中的某个特定点,如方法调用、异常抛出等。在 Spring AOP 中,连接点主要指方法调用。
  • 切入点(Pointcut):切入点定义了哪些连接点会被织入通知,它是一组连接点的集合。通过切入点表达式可以精确地指定哪些方法需要应用切面的通知。例如,execution(* com.example.service.*.*(..))表示com.example.service包下所有类的所有方法都是切入点。

以一个简单的日志切面为例,使用注解方式配置:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LogAspect {@Around("execution(* com.example.service.*.*(..))")public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("方法开始执行: " + joinPoint.getSignature().getName());Object result = joinPoint.proceed();System.out.println("方法执行结束: " + joinPoint.getSignature().getName());return result;}
}

上述代码定义了一个日志切面LogAspect,使用@Around注解定义了一个环绕通知,切入点表达式为execution(* com.example.service.*.*(..)),表示对com.example.service包下所有类的所有方法进行日志记录。

面试题 3:AOP 有哪些应用场景?

答案

  • 日志记录:在方法执行前后记录日志,用于记录系统的操作日志,方便追踪和调试。如记录用户的登录操作、订单的创建和修改操作等。
  • 事务管理:通过 AOP 可以将事务管理的逻辑从业务代码中分离出来,在方法执行前后自动开启和提交事务,或者在出现异常时回滚事务。例如在一个电商系统中,商品的下单、库存扣减等操作需要在一个事务中进行,通过 AOP 可以很方便地实现事务管理。
  • 权限控制:在方法执行前进行权限检查,确保只有具有相应权限的用户才能访问特定的方法。比如在一个后台管理系统中,只有管理员用户才能执行删除用户的操作,通过 AOP 可以在删除用户方法执行前进行权限校验。
  • 性能监控:通过 AOP 可以在方法执行前后记录时间,计算方法的执行时间,用于性能监控和优化。例如在一个高并发的系统中,对一些核心业务方法进行性能监控,找出性能瓶颈。

掌握 Spring 框架的 IOC 和 AOP 原理,是理解和使用 Spring 框架的关键。下一篇,我们将深入探讨 Spring MVC 相关知识,继续为你的春招面试助力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/68055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ssm基于HTML5的红酒信息分享系统

SSM基于HTML5的红酒信息分享系统是一个专注于红酒领域的综合性信息平台&#xff0c;旨在为红酒爱好者、从业者以及普通消费者提供一个便捷的交流与获取红酒相关信息的空间。 一、系统背景与意义 随着人们生活水平的提高和消费观念的转变&#xff0c;红酒作为一种高雅的饮品&a…

【python】subprocess.Popen执行adb shell指令进入linux系统后连续使用指令,出现cmd窗口阻塞问题

问题描述 subprocess.Popen执行adb shell指令进入linux系统后出现cmd窗口阻塞问题&#xff0c;需要手动关闭cmd才会继续执行其他指令。 解决方案 1、cmd指令后面加入exit\n关闭exe进程 2、subprocess.Popen()添加内置参数creationflagssubprocess.CREATE_NO_WINDOW隐藏窗口弹…

细说机器学习算法之过拟合与欠拟合

系列文章目录 第一章&#xff1a;Pyhton机器学习算法之KNN 第二章&#xff1a;Pyhton机器学习算法之K—Means 第三章&#xff1a;Pyhton机器学习算法之随机森林 第四章&#xff1a;Pyhton机器学习算法之线性回归 第五章&#xff1a;Pyhton机器学习算法之有监督学习与无监督…

深度学习中的通道(Channel)概念详解

1. 通道的基本概念 通道(Channel)是深度学习中的一个重要概念&#xff0c;它在不同场景下有不同的具体含义。理解通道概念对于理解深度学习模型的结构和工作原理至关重要。 2. 大语言模型中的通道 2.1 全连接层的通道概念 2.1.1 基本结构 输入&#xff1a;[batch_size, in…

Windows Docker Desktop安装及使用 Docker 运行 MySQL

Docker Desktop是Docker的官方桌面版&#xff0c;专为Mac和Windows用户设计&#xff0c;提供了一个简单易用的界面来管理和运行Docker容器。它集成了Docker引擎&#xff0c;为开发人员提供了一个快速、可靠、可扩展的方式来构建、运行和管理应用。DockerDesktop的优势在于&…

TTL 在 Redis 缓存中的作用

Redis TTL&#xff08;Time To Live&#xff09;与缓存的关系 TTL&#xff08;Time To Live&#xff0c;生存时间&#xff09;是 Redis 提供的一种自动过期机制&#xff0c;用于控制键值对的存活时间。当 TTL 到期后&#xff0c;Redis 会自动删除该键&#xff0c;避免长期占用…

人形机器人,自动驾驶“老炮”创业第二站

造一台人形机器人&#xff0c;或许正在成为2025年最炙手可热的事情。 从去年第四季度开始&#xff0c;伴随着大模型应用的深入&#xff0c;具身智能概念被点燃&#xff0c;其中最鲜明的一个特点是&#xff0c;大量自动驾驶大佬的转行加入。 随便说几个比较有分量的&#xff0…

MFC常用操作

1&#xff0c;获取STATIC控件的值 CString str; m_STATIC2.GetWindowText(str);//获取STATIC控件的值 MessageBox(str); 2.设置EDIT控件的值 m_EDIT2.SetWindowText(str); GetDlgItem(IDC_EDIT1)->SetWindowText("Leave"); 3.移动控件 m_EDIT2.SetWindowPos(…

Flutter_学习记录_基本组件的使用记录

1.TextWidge的常用属性 1.1TextAlign: 文本对齐属性 常用的样式有&#xff1a; TextAlign.center 居中TextAlign.left 左对齐TextAlign.right 有对齐 使用案例&#xff1a; body: Center(child: Text(开启 TextWidget 的旅程吧&#xff0c;珠珠, 开启 TextWidget 的旅程吧&a…

什么是COLLATE排序规则?

在当今数字化世界中&#xff0c;数据的整理、比较和排序是至关重要的。在数据库管理和编程语言中&#xff0c;我们经常需要对字符串进行排序&#xff0c;以展示或处理信息。为了实现这一点&#xff0c;各种系统和工具提供了排序规则&#xff0c;其中COLLATE排序规则就是其中的一…

打印输入单词字符数量统计直方图-C语言第二版

1. 编程要求 多年前写过一篇用 C 语言实现打印单词字符数量统计的直方图的文章, 现在看上去有些混乱, 对一些任务划分不清晰, 全部混在一起. 于是重写了这个编程题, 希望可以给初学者一些参考, 并且我分别用 C, C, Java, Python 四种语言完成了这道编程题, 有兴趣的可以看我另…

【QT】-explicit关键字

explicit explicit 是一个 C 关键字&#xff0c;用于修饰构造函数。它的作用是防止构造函数进行隐式转换。 为什么需要 explicit&#xff1f; 在没有 explicit 的情况下&#xff0c;构造函数可以用于隐式类型转换。这意味着&#xff0c;如果你有一个接受某种类型的参数的构造…

【C++模板】:如何判断自定义类型是否实现某个函数

一、引子 偶尔我们会面对这样的尴尬的场景&#xff0c;我们需要显示的去判断在某个自定义类型中&#xff0c;是否已经提供了我们期待的API接口&#xff0c;以避免产生“莫须有”的错误。阁下该如何破解此问题&#xff01; 这里&#xff0c;直接给出一种通用的方法&#xff0c;…

认识Django项目模版文件——Django学习日志(二)

1.默认文件介绍 └── djangoproject1/├── djangoproject1/│ ├── urls.py [URL和函数的对应关系]【常用文件】│ ├── settings.py [项目配置文件]【常用文件】│ ├── _init_.py│ ├── wsgi.py [接受网络请求] 【不要动】│ └──…

【JS逆向】前端加密对抗基础

目录 逆向基础断掉调试基本常见的加解密方式 encrypt-labs靶场搭建过程靶场基本教程AES加密key前端体现(固定key)AES服务端获取keyRSA非对称加密DES加密存在规律key明文加签sign加签key在服务端signAESRAS组合 逆向基础 断掉调试 通过浏览器站点控制台(F12)&#xff0c;进行断…

C# 多线程同步(Mutex | Semaphore)

Mutex: 用于保护临界区&#xff0c;确保同一时间只有一个线程能够访问共享资源&#xff1b; Semaphore: 允许同时有多个线程访问共享资源&#xff0c;但会限制并发访问的数量。 Mutex运行输出 Semaphore运行输出 namespace SyncThreadDemo {internal class Program{static stri…

复位信号的同步与释放(同步复位、异步复位、异步复位同步释放)

文章目录 背景前言一、复位信号的同步与释放1.1 同步复位1.1.1 综述1.1.2 优缺点 1.2 recovery time和removal time1.3 异步复位1.3.1 综述1.3.2 优缺点 1.4 同步复位 与 异步复位1.5 异步复位、同步释放1.5.1 总述1.5.2 机理1.5.3 复位网络 二、思考与补充2.1 复…

git远程仓库如何修改

1.需要做的事情&#xff1a;把git的远程仓库修改掉&#xff0c;在git创建一个自己的仓库 如果你是私有化的话&#xff0c;可以生成一个自己token令牌也可以。到时候push的时候会让你登录你就可以输入你的token令牌和用户名。 2.查看当前仓库的远程地址是不是自己的 &#xff…

mysql 学习3 SQL语句--整体概述。SQL通用语法;DDL创建数据库,查看数据库,删除数据库,使用数据库;

SQL通用语法 SQL语句分类 DDL data definition language : 用来创建数据库&#xff0c;创建表&#xff0c;创建表中的字段&#xff0c;创建索引。因此成为 数据定义语言 DML data manipulation language 有了数据库和表以及字段后&#xff0c;那么我们就需要给这个表中 添加数…

【xcode 16.2】升级xcode后mac端flutter版的sentry报错

sentry_flutter 7.11.0 报错 3 errors in SentryCrashMonitor_CPPException with the errors No type named terminate_handler in namespace std (line 60) and No member named set_terminate in namespace std 替换sentry_flutter版本为&#xff1a; 8.3.0 从而保证oc的…