Java后端高频面经——Spring、SpringBoot、MyBatis
-
Spring定义一个Bean有哪些方法?依赖注入有哪些方法?
(1)定义Bean的方法
-
注解定义Bean,@Component
用于标记一个类作为Spring的bean。当一个类被@Component注解标记时,Spring会将其实例化为一个bean,并将其添加到Spring容器中。
-
配置文件定义Bean
(2)依赖注入的方法
- 字段(Field):最直接地在类的字段上使用。
public class MyClass {@Autowiredprivate MyDependency myDependency; }
- 构造器(Constructor):在构造器上使用,用于构造器注入。
public class MyClass {private MyDependency myDependency;@Autowiredpublic MyClass(MyDependency myDependency) {this.myDependency = myDependency;} }
- 方法(Method):也可以在一个方法上使用,通常是一个 setter 方法。
public class MyClass {private MyDependency myDependency;@Autowiredpublic void setMyDependency(MyDependency myDependency) {this.myDependency = myDependency;} }
-
-
介绍IOC、AOP、反射
(1)IOC
Spring IOC容器通过
①封装对象的创建(将对象的创建过程交给Spring管理,从而实现了控制反转)和生命周期管理(管理对象的初始化和销毁过程),
②使用依赖注入来解耦对象之间的依赖关系(通过 Spring 容器将类 A 所依赖的 B 的实例注入到 A 中,这样 A 和 B 不再直接依赖,而是通过容器来提供),
③利用反射和配置元数据动态地创建和管理对象(当 Spring 容器启动时,它会根据配置文件或注解(元数据)扫描类的信息,通过反射技术实例化对象,而不需要编写具体的
new
代码。反射让 Spring 能够动态地操作类的构造函数、方法等), ④同时提供作用域管理功能(对象的生命周期和可见性范围。Spring 提供了多种作用域,容器会根据作用域来管理对象的实例化、销毁等过程。Singleton(单例)、Prototype(原型)、Request、Session、Application 等作用域)。
(2)AOP
面向切面编程,AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装起来,以减少系统的重复代码,降低模块间的耦合度。
两个例子:权限校验拦截器、动态切换数据源。
Spring AOP的实现依赖于动态代理技术。动态代理是在运行时动态生成代理对象,而不是在编译时。
注解 @Aspect 用于定义切面,标注在切面类上。 @Pointcut 定义切点,标注在方法上,用于指定连接点。 @Before 在方法执行之前执行通知。 @After 在方法执行之后执行通知。 @Around 在方法执行前后都执行通知。 (3)反射
允许在运行时动态地查询和操作类、方法、字段等信息,并且能够通过反射来调用类中的方法或修改类的属性。反射机制的核心原理是:通过
Class
类来获取类的结构信息,并且使用这些信息在运行时动态地操作类的对象。IOC、DI、动态代理就是用到了反射。①获取class对象:可以通过类的
Class
对象来访问类的信息。Class<?> clazz = Class.forName("Person"); //括号里的内容可以是程序运行时才输入的内容
②查询类的结构信息:通过
Class
对象,可以获取类的构造方法、方法、字段、接口、父类等信息。Method[] methods = clazz.getMethods(); // 获取所有公共方法 Field[] fields = clazz.getFields(); // 获取所有公共字段 Constructor[] constructors = clazz.getConstructors(); // 获取所有公共构造函数
③动态创建对象
Constructor<?> constructor = clazz.getConstructor(); // 获取无参构造 Object instance = constructor.newInstance(); // 使用构造函数创建对象实例
④调用方法
Method method = clazz.getDeclaredMethod("myMethod", String.class); method.setAccessible(true); // 如果是私有方法,需要设置访问权限 method.invoke(obj, "parameter"); // 调用方法
-
介绍动态代理、静态代理?
代理模式是设计模式中的一种,它通过提供代理对象来控制对原对象的访问。代理对象充当中介,通常在请求实际操作之前或之后做一些额外的工作(例如检查权限、缓存结果、延迟加载等)。
控制访问:代理可以控制对实际对象的访问,增加额外的功能(如安全性、权限管理、日志记录等)。
延迟加载:通过代理,可以延迟初始化或执行耗时的操作,直到真正需要时才执行。
性能优化:代理对象可以缓存结果,减少重复计算或请求,提高性能。
增强功能:代理对象可以在不修改原对象代码的情况下,为其增加新的功能,如事务管理、日志记录等。
(1)动态代理
动态代理是在运行时创建代理对象,代理对象在运行时被动态地生成,因此不需要在编译时就确定代理类。Java 提供了两种方式来实现动态代理:
- JDK 动态代理
- 通过
java.lang.reflect.Proxy
类和InvocationHandler
接口动态生成代理类。JDK 动态代理要求目标类实现一个接口。
- 通过
- CGLIB(Code Generation Library)代理
- 通过字节码生成技术,动态创建目标类的子类来实现代理。CGLIB 代理不要求目标类实现接口,而是通过继承目标类来实现代理。
(2)静态代理
代理类是在编译时就已经写好并且确定的。是由开发者手动编写的,并且在程序运行之前就已经存在。例如,你在编写代码时就知道你需要一个
Proxy
类,它会代理RealSubject
类的方法。在静态代理中,代理类和目标类的关系是固定的,编译时就已经确定。 代理模式是JAVA的一种设计模式,而AOP是Spring框架中的一个特性,是使用了动态代理来实现的。
- JDK 动态代理
-
Spring的循环依赖的原因以及解决方法;(众安)
循环依赖指的是两个类中的属性相互依赖对方:例如 A 类中有 B 属性,B 类中有 A属性,从而形成了一个依赖闭环。
Spring中的循环依赖问题有三种情况:
- 第一种:通过构造方法进行依赖注入时产生的循环依赖问题。
- 第二种:通过setter方法进行依赖注入且是在多例(原型)模式下产生的循环依赖问题。
- 第三种:通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。
单例模式适用于全局唯一的资源管理,如配置管理、日志记录、数据库连接池等。它的特点是保证类在全局范围内只有一个实例,所有地方都使用同一个对象。
多例模式适用于需要多个独立实例的场景,如用户会话、任务调度、订单管理等。每个实例有自己的状态和行为,不共享数据。
只有【第三种方式】的循环依赖问题被 Spring 解决了,其他两种方式在遇到循环依赖问题时,Spring都会产生异常。
(1)Spring实例化Bean:Spring尝试创建A的实例,发现A依赖B,因此需要实例化B。Spring在创建B时,发现B依赖A,但此时A还没有完成初始化,所以Spring会创建A的空对象并将其放入
singletonObjects
一级缓存中并开始创建B。(3)循环依赖暴露
- 当Spring尝试创建B时,由于A还没有完全初始化,Spring会把A实例(未完全初始化)提前暴露到
earlySingletonObjects
二级缓存中,这时A成为一个半初始化的Bean。 - B可以通过
earlySingletonObjects
二级缓存获得这个提前暴露的A对象,从而完成B的依赖注入。
(3)初始化Bean
-
依赖注入完成后,Spring继续初始化B(如调用
@PostConstruct
等),然后将B放入三级singletonFactories
缓存中,表示B已经完全初始化。 -
Spring继续完成A的初始化工作,注入B,完成生命周期的其他部分,并将A放入三级
singletonFactories
缓存中,表示A也已经完全初始化。
(4)总结
- 在依赖注入过程中,Spring通过
earlySingletonObjects
二级缓存提供了B对A的依赖,通过singletonFactories
三级缓存提供了A对B的依赖,从而打破了循环依赖。
-
列举几个Spring常用的注解?(美团)
注解 作用 @Autowired 自动装配bean,当Spring容器中存在与要注入的属性类型匹配的bean时,它会自动将bean注入到属性中 @Component Spring会将一个类实例化为一个bean,并将其添加到Spring容器中。 @Configuration 用于标记一个类作为Spring的配置类,配置类可以包含@Bean注解的方法,用于定义和配置bean,作为全局配置。 @Bean 用于标记一个方法作为Spring的bean工厂方法,当一个方法被@Bean注解标记时,Spring会将该方法的返回值作为一个bean,并将其添加到Spring容器中 @Service 用于标记服务层的bean,是@Component注解的特例,一般标记在业务service的实现类。 @Repository 用于标记数据访问层的bean,它也是@Component注解的特例。 @Controller 用于标记控制层的bean,它也是@Component注解的特例。 -
spring、springboot、SpringMVC的区别及关系?(康泰)
Spring 是一个全面的应用开发框架,提供了全面的基础设施和功能支持。
Spring MVC 是 Spring 框架中的一个模块,专门用于 Web 开发,采用 MVC 模式来处理 Web 请求和响应。它依赖于 Spring 框架的核心功能,如 IoC 和 AOP。
Spring Boot 是一个基于 Spring 的项目,它封装了 Spring 和其他相关技术(如 Spring MVC、Spring Data、Spring Security 等),提供自动配置、快速项目启动器、内嵌服务器三大功能,使开发者能够快速启动和构建 Spring 应用。
- 自动配置
- 快速项目启动器,通过引入不同的 Starter,可以快速集成常用的框架和库(如数据库、消息队列、Web 开发等),极大地提高了开发效率。
- 内嵌服务器(Tomcat、Jetty、Undertow),无需额外配置,即可将应用打包成可执行的 JAR 文件,方便部署和运行。
Spring+Spring MVC = Spring Boot
-
springboot的自动配置原理?(美团、得物)springBoot启动机制,启动之后做了哪些步骤?(B站)
-
SpringBoot重要注解
@SpringBootApplication 用于标注主应用程序类,标识一个Spring Boot应用程序的入口点,同时启用自动配置和组件扫描。 @Controller 标识控制器类,处理HTTP请求。 @RestController 结合@Controller和@ResponseBody,返回RESTful风格的数据。 @Service 标识服务类,通常用于标记业务逻辑层。 @Repository 标识数据访问组件,通常用于标记数据访问层。 @Component 通用的Spring组件注解,表示一个受Spring管理的组件。 @Autowired 用于自动装配Spring Bean。 @Value 用于注入配置属性值。 @RequestMapping 用于映射HTTP请求路径到Controller的处理方法。 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 简化@RequestMapping的GET、POST、PUT和DELETE请求。 @Configuration 用于指定一个类为配置类,其中定义的bean会被Spring容器管理。 -
怎么用原生的MyBatis去查询?
(1)配置MyBatis: 在配置文件中配置数据源、MyBatis的Mapper文件位置等信息。
(2)创建实体类:创建与数据库表对应的实体类,字段名和类型需与数据库表保持一致。
public class User {private Long id;private String username,private String email,// Getters and setters }
(3)编写SQL映射文件:在resources目录下创建XML文件,定义SQL语句和映射关系。
<mapper namespace="com.example.dao.UserMapper"><select id="selectUserById" resultType="com.example.model.User">SELECT * FROM users WHERE id = #{id}</select> </mapper>
(4)编写DAO接口:创建DAO接口,定义查询方法。
public interface UserMapper {User selectUserById(Long id); }
(5)编写具体的SQL查询语句:在XML文件中编写对应的SQL语句。
(6)调用查询方法:在服务层或控制层中调用DAO接口中的方法进行查询。
// 在Service层中调用 User user = userMapper.selectUserById(1);
-
MyBatis里的 # 和 $ 的区别?
-
Mybatis 在处理 #{}时,会创建预编译的 SQL 语句,将 SQL 中的 #{} 替换为?号,在执行 SQL 时会为预编译 SQL 中的占位符(?)赋值,调用 PreparedStatement 的 set 方法来赋值,预编译的 SQL 语句执行效率高,并且可以防止SQL注入,提供更高的安全性,适合传递参数值。
-
Mybatis 在处理 ${} 时,只是创建普通的 SQL语句,然后在执行 SQL语句时 MvBatis 将参数直接拼入到 SQL里,不能防止 SQL注入,因为参数直接拼接到 SQL语句中,如果参数未经过验证、过滤,可能会导致安全问题。
比如:
<select id="getUserByUsername" resultType="User">SELECT * FROM users WHERE username = '${username}' </select>
在这个查询中,
${username}
会直接被传入的username
值替换,假如传入的username
是恶意的,例如"' OR 1=1"
,查询语句就变成了:SELECT * FROM users WHERE username = '' OR 1=1
这就是典型的 SQL 注入,因为
$
直接拼接了参数值,导致不安全的 SQL 被执行。大多数情况下都应该使用
#
,特别是涉及到用户输入的值时。它可以安全地处理用户输入,避免 SQL 注入。只有在确实需要拼接动态 SQL 的结构部分(如表名、列名)时,才应该使用$
。
-
MybatisPlus和Mybatis的区别?(百度)
MybatisPlus是一个基于MyBatis的增强工具库。
- CRUD操作:MybatisPlus通过继承BaseMapper接口,提供了一系列内置的快捷方法,使得CRUD操作更加简单,无需编写重复的SQL语句。
- 代码生成器:MvbatisPlus提供了代码生成器功能,可以根据数据库表结构自动生成实体类、Mapper接口以及XML映射文件,减少了手动编写的工作量。
- 通用方法封装:MybatisPlus封装了许多常用的方法,如条件构造器、排序、分页查询等,简化了开发过程,提高了开发效率。
- 分页插件:MybatisPlus内置了分页插件,支持各种数据库的分页查询,开发者可以轻松实现分页功能,而在传统的MyBatis中,需要开发者自己手动实现分页逻辑。
- 多租户支持:MvbatisPlus提供了多租户的支持,可以轻松实现多租户数据隔离的功能。
- 注解支持:MvbatisPlus引入了更多的注解支持,使得开发者可以通过注解来配置实体与数据库表之间的映射关系,减少了XML配置文件的编写。
相关文章:
Java后端高频面经——Spring、SpringBoot、MyBatis
Spring定义一个Bean有哪些方法?依赖注入有哪些方法? (1)定义Bean的方法 注解定义Bean,Component 用于标记一个类作为Spring的bean。当一个类被Component注解标记时,Spring会将其实例化为一个bean࿰…...
扩散模型中三种加入条件的方式:Vanilla Guidance,Classifier Guidance 以及 Classifier-Free Guidance
扩散模型主要包括两个过程:前向扩散过程和反向去噪过程。前向过程逐渐给数据添加噪声,直到数据变成纯噪声;反向过程则是学习如何从噪声中逐步恢复出原始数据。在生成过程中,模型从一个随机噪声开始,通过多次迭代去噪&a…...

Banana Pi OpenWRT One Wifi6 OpenWrt社区官方开源路由器评测
第一款不可破解、开源、版权软件、符合 FCC、CE 和 RoHS 的维修权路由器 OpenWRT项目今年已经20岁了,为了纪念这一时刻,Banana Pi OpenWrt One/AP-24.XY路由器开发系统已经上市。这是OpenWRT团队与硬件公司的第一个联合项目。选择 Banana Pi,…...
9.1go结构体
Go不是完全面向对象的,没有类的概念,所以结构体应该承担了更多的责任。 结构体定义 使用 type 和 struct 关键字定义: type Person struct { Name string Age int } 字段可以是任意类型,包括其他结构体或指针。 字段名以大写…...

Manus全球首个通用Agent,Manus AI:Agent应用的ChatGPT时刻
文章目录 前言Manus AI: 全球首个通用AgentManus AI: 技术架构与创始人经历AI Agent的实现框架与启示AI Agent的发展预测行业风险提示 前言 这是一篇关于Manus AI及其在通用人工智能领域的应用和前景的报告,主要介绍了Manus AI的产品定位、功能、技术架构、创始人经…...

【SAP-PP】生产版本维护
一、基本概念 生产版本:用于定义一种产品,不同的生产方式,包含物料清单(BOM)和工艺路线的信息,给生产带来更多的灵活性。在做产品需求计划时和产品生产时(创建生产订单、生产订单下达前和生产订…...
软考 中级软件设计师 考点笔记总结 day01
文章目录 软考1.0上午考点下午考点 软考1.11、数值及其转换2、计算机内数据表示2.1、定点数 - 浮点数2.2、奇偶校验 和 循环冗余校验 (了解)2.3、海明码 (掌握)2.4、机器数 软考1.0 上午考点 软件工程基础知识: 开发模型、设计原则、测试方…...

K8s控制器Deployment详解
回顾 ReplicaSet 控制器,该控制器是用来维护集群中运行的 Pod 数量的,但是往往在实际操作的时候,我们反而不会去直接使用 RS,而是会使用更上层的控制器,比如说 Deployment。 Deployment 一个非常重要的功能就是实现了 Pod 的滚动…...

【微知】Centos如何迁移到Anolis系统的失败记录?(yum -y install centos2anolis、centos2anolis.py)
背景 本文记录如何从centos 8迁移到anolis系统。 详细步骤 下载迁移repo wget https://mirrors.openanolis.cn/anolis/migration/anolis-migration.repo -O /etc/yum.repos.d/anolis-migration.repo下载centos2anolis工具包 yum -y install centos2anolis安装额外工具包 …...

在 macOS 上使用 CLion 进行 Google Test 单元测试
介绍 Google Test(GTest)是 Google 开源的 C 单元测试框架,它提供了简单易用的断言、测试夹具(Fixtures)和测试运行机制,使 C 开发者能够编写高效的单元测试。 本博客将介绍如何在 macOS 上使用 CLion 配…...
Python SQLite3 保姆级教程:从零开始学数据库操作
Python SQLite3 保姆级教程:从零开始学数据库操作 本文适合纯新手!无需任何数据库基础,跟着步骤操作即可掌握 SQLite3 的核心用法。 目标:让你像用记事本一样轻松操作数据库! 目录 什么是 SQLite3?环境准…...
深度解析:视频软编码与硬编码的优劣对比
视频编码 一、基本原理与核心技术 压缩原理 通过时空冗余消除实现数据压缩: 空间冗余:利用帧内预测(如DC/角度预测)消除单帧内相邻像素相似性。时间冗余:运动估计与补偿技术(ME/MC)减少连续帧间…...
Azure云生态系统详解:核心服务、混合架构与云原生概念
核心服务:深入掌握Azure SQL Database、Azure Database for PostgreSQL、Azure Database for MySQL的架构、备份恢复、高可用性配置(如Geo-Replication、自动故障转移组、异地冗余备份)。混合架构:熟悉Azure Arc(管理混…...

人工智能之数学基础:正交矩阵
本文重点 正交矩阵是线性代数中一个重要的特殊矩阵,它在许多领域都有广泛的应用。 什么是正交矩阵 如图所示,当矩阵A满足如上所示的条件的时候,此时我们就可以认为是正交矩阵,需要注意一点矩阵A必为方阵。 正交矩阵的充要条件 …...

分布式锁—7.Curator的分布式锁
大纲 1.Curator的可重入锁的源码 2.Curator的非可重入锁的源码 3.Curator的可重入读写锁的源码 4.Curator的MultiLock源码 5.Curator的Semaphore源码 1.Curator的可重入锁的源码 (1)InterProcessMutex获取分布式锁 (2)InterProcessMutex的初始化 (3)InterProcessMutex.…...

【笔记】STM32L4系列使用RT-Thread Studio电源管理组件(PM框架)实现低功耗
硬件平台:STM32L431RCT6 RT-Thread版本:4.1.0 目录 一.新建工程 二.配置工程 编辑 三.移植pm驱动 四.配置cubeMX 五.修改驱动文件,干掉报错 六.增加用户低功耗逻辑 1.设置唤醒方式 2.设置睡眠时以及唤醒后动作 编辑 3.增加测试命…...
C++什么是深复制和浅复制,构造函数和析构函数,哪一个可以写成虚函数,为什么?
在C之中深复制是指对于值类型复制它的值,对于指针类型不仅仅复制指针指向的值,还会重新分配一个内存空间用于放置复制的值(对动态分配的内存进行重新分配和内存复制),这种深复制不会出现悬空指针的问题,但是…...

从连接到交互:SDN 架构下 OpenFlow 协议的流程与报文剖析
在SDN架构中,交换机与控制器之间的通信基于 OpenFlow协议,其设计目的是实现控制平面与数据平面的解耦。以下是 交换机连接控制器 和 数据包进入交换机触发交互 的详细流程及协议报文分析: 一、交换机连接控制器的流程(初始化阶段&…...

第七课:Python反爬攻防战:Headers/IP代理与验证码
在爬虫开发过程中,反爬虫机制成为了我们必须面对的挑战。本文将深入探讨Python爬虫中常见的反爬机制,并详细解析如何通过随机User-Agent生成、代理IP池搭建以及验证码识别来应对这些反爬策略。文章将包含完整的示例代码,帮助读者更好地理解和…...

Golang学习笔记_47——访问者模式
Golang学习笔记_44——命令模式 Golang学习笔记_45——备忘录模式 Golang学习笔记_46——状态模式 文章目录 一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 编译器实现2. 财务系统3. UI组件系统 四、Go语言实现示例完整实现代码执行结果 五、…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...