Spring知识点(2)

news/2025/9/27 11:11:23/文章来源:https://www.cnblogs.com/xiaoqian01/p/19083397

 

一、有哪些依赖注入方式?

  • 构造方法注入:通过调用类的构造方法,推荐用于强依赖(没有依赖对象就没法工作)。这也是官方推荐的注入方式。好处:依赖不可变(final修饰)、更安全。
@Component
public class UserService {private final UserDao userDao;// Spring 会自动注入 UserDao@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}
}
  • Setter注入:适合可选依赖(有无都能运行)
@Component
public class UserService {private UserDao userDao;@Autowiredpublic void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
  • 字段注入:直接在字段上加@Autowired。(简单,但不利于单元测试mock,因为会依赖Spring框架)

二、Spring有哪些自动装配的方式

1、什么是自动装配

  装配:把bean之间的依赖关系配置清楚

  自动装配:让Spring容器自己根据规则把依赖对象诸如进去,而不是开发者手动写。这样可以减少配置,提升开发效率。

2、Spring提供了哪几种自动装配类型

  • no(默认值):不自动装配,必须显式依赖(XML里面写<property>)
  • byName:根据属性名找到和Bean的id一样的Bean注入
  • byType:根据属性的类型找到容器里唯一匹配的Bean注入
  • constructor:根据构造方法参数的类型,去容器里找匹配的 Bean 注入。

【注意】

在 Spring Boot 和注解驱动里,主要用:

  • @Autowired(默认 byType,可结合 @Qualifier 指定名字)

  • @Resource(JDK自带,默认 byName,找不到再 byType)

  • @Inject(JSR-330 标准注解,行为类似 @Autowired)

// 接口
public interface UserDao {void save();
}// 第一个实现
@Component("mysqlUserDao")
public class UserDaoMysql implements UserDao {@Overridepublic void save() {System.out.println("保存到 MySQL 数据库");}
}// 第二个实现
@Component("oracleUserDao")
public class UserDaoOracle implements UserDao {@Overridepublic void save() {System.out.println("保存到 Oracle 数据库");}
}

 

三、Spring中Bean的作用域有哪些

  • singleton(默认):在一个Spring 容器(ApplicationContext)中,只创建一个 Bean 实例。每次 getBean() 拿到的都是同一个对象。
  • prototype:每次调用 getBean(),都会新建一个对象。
  • request(仅 Web 应用中有效):每个 HTTP 请求都会创建一个新的 Bean。Bean 生命周期和一次请求绑定,请求结束后 Bean 被销毁。
  • session(仅 Web 应用中有效):每个 HTTP 会话(Session)只对应一个 Bean。同一个 Session 里的请求共享 Bean,不同 Session 用不同 Bean。
@Component
@Scope("prototype")   // 或 "request" / "session"
public class UserService {}
  • Session = 会话

  • 在 Web 里,Session 表示 用户从打开浏览器访问网站,到关闭浏览器/超时退出的这一段交互过程

四、Spring中的单例Bean会存在线程安全问题吗

  Spring的单例Bean不是天然线程安全的。是否有问题,取决于Bean是否有状态。

  • 无状态Bean(只做方法调用,不保存共享数据):线程安全
  • 有状态Bean(持有成员变量,并且会被多个线程同时读写):线程不安全

  解决办法:

  • 改为多例(prototype):每次请求都新建一个实例-->不共享-->没有线程安全问题。但这样会失去单例的优势,容器管理和性能都会受影响。
  • 避免在Bean中设计为无状态,方法里只用局部变量
  • 使用ThreadLocal 保存状态(推荐 ✅):给每个线程准备一份独立副本,避免了线程之间的数据覆盖。
@Service
public class UserContextService {private ThreadLocal<String> currentUser = new ThreadLocal<>();public void setUser(String user) {currentUser.set(user);  // 每个线程有自己独立的副本}public String getUser() {return currentUser.get();  // 取的就是当前线程的值}public void clear() {currentUser.remove();  // 防止内存泄漏(重要!)}
}

 

五、说说循环依赖

1、什么是循环依赖

  两个或多个Bean互相依赖,形成“死循环”,只在单例下会出现。如果是prototype的话会无限套娃。

  那Spring能解决哪些情况?

  • 两边都是构造器注入(不支持):无法提前暴露“半成品”对象,会直接报错。
  • 两边都是setter/字段注入(支持):Spring创建A会调用构造方法得到一个空对象,把A的工厂放到三级缓存。给A注入依赖时发现需要B,就去创建B。-->创建B的时候发现需要A,就去一级、二级缓存找,找不到就调用三级缓存的ObjectFactory得到一个“早期A”,把这个早期A放进二级缓存,然后注入到B。B创建完后,返回给A。完成A的初始化。这时候A、B都是成品Bean,放进一级缓存。
  • 一边构造器、一边setter注入->看情况(A构造器、Bsetter):若Spring先创建A,构造器立刻需要B,但B还没创建-->报错❌。若Spring先创建B,B可以先用setter注入半成品A-->✅ 能成功。

六、Spring怎么解决循环依赖

1️⃣ 一级缓存:singletonObjects

  • 存放 完全创建好的单例 Bean(成品)。

  • 以后再来 getBean(),直接从这里拿。

2️⃣ 二级缓存:earlySingletonObjects

  • 存放 提前曝光的单例 Bean(早期引用)

  • 这里的 Bean 已经实例化,但可能还没注入属性、没初始化。

  • 如果别的 Bean 需要,可以先用它占个坑,后面再补全。

3️⃣ 三级缓存:singletonFactories

  • 存放 ObjectFactory(对象工厂),可以生成早期 Bean。

  • 为什么要三级?因为有些 Bean 可能需要 AOP 代理,必须等真正用到的时候才生成代理对象 → 所以放工厂。

👉 三级缓存的目的:保证 Bean 能被提前曝光,同时还能支持 代理增强(AOP)

 

七、为什么要三级缓存?二级不行吗

  A是一个Bean,它需要被代理(比如加了@Transactional),如果只用二级缓存,把原始的A暴露出去,B会拿到“未代理的A”。后面再生成代理对象的时候,B里注入的还是旧的原始对象-->功能失效。

  三级缓存的作用:三级缓存存放的是 ObjectFactory,不是 Bean 本身。当别的 Bean 需要 A 时,可以通过这个工厂去获取“真正的早期对象”:

  • 如果 A 不需要代理,就返回原始对象;

  • 如果 A 需要代理,就在这里生成代理对象返回。

  所以,二级缓存只能解决循环依赖,但无法保证AOP代理生效。

八、@Autowired的实现原理

@Service
public class UserService {@Autowiredprivate UserDao userDao;
}
  • Spring实例化UserService,AutowiredAnnotationBeanPostProcessor扫描到userDao字段上有@Autowired,容器里找userDao类型的Bean,反射调用:
field.setAccessible(true);
field.set(userService, userDaoImpl);

 


AOP

九、说说什么是AOP

  面向切面编程,简单说就是把一些业务逻辑中的相同的代码抽取到一个独立的模块中,让业务逻辑更加清爽。AOP可以将遍布应用各处的功能分离出来形成可重用的组件。

  AOP的核心就是动态代理,如果实现了接口就用JDK动态代理,否则用CGLIB动态代理。

  核心概念:

  • 切面:切点+通知的组合
  • 切点:要拦截的方法
  • 通知:增强的逻辑
    • 前置通知Before
    • 后置通知After
    • 环绕通知Around
    • 异常通知:AfterThrowing
    • 最终通知AfterReturning
//1.业务类(目标对象)
import org.springframework.stereotype.Service;@Service
public class UserService {public void addUser() {System.out.println("执行 UserService.addUser()");}
}//2.切面类(ASpect+advice)
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LogAspect {// 切点:匹配 UserService 的 addUser 方法@Pointcut("execution(* com.example.demo.UserService.addUser(..))")public void addUserPointcut() {}// 前置通知@Before("addUserPointcut()")public void beforeAddUser() {System.out.println("Before: 准备添加用户");}// 后置通知@After("addUserPointcut()")public void afterAddUser() {System.out.println("After: 添加用户完成");}
}//3.启动类(开启AOP)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@EnableAspectJAutoProxy // 开启 AOP 支持
public class DemoApplication {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(DemoApplication.class, args);UserService userService = context.getBean(UserService.class);userService.addUser();}
}//结果
Before: 准备添加用户
执行 UserService.addUser()
After: 添加用户完成

 

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

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

相关文章

成都电子商务网站建设非寻服饰网站建设规划书

文章目录 “预训练微调大模型”的模式以提示/指令模式直接使用大模型“预训练微调大模型”模式和Prompt/Instruct模式的异同小结 “预训练微调大模型”的模式 经过预训练的大模型所习得的语义信息和所蕴含的语言知识&#xff0c;很容易向下游任务迁移。NLP应用人员可以根据自己…

超越实习期的AI自动化工具:播客工作流与Slack导出器实战

本文详细介绍实习期间基于Claude AI模型开发的两个自动化工具:播客工作流年省1250小时人工,Slack导出器实现智能知识检索。包含技术架构、问题解决方案和实际应用效果,展现AI如何增强企业工作效率。超越实习期的实习…

调度器的各项指标以及计算方式

CPU利用率 \[利用率=\frac{忙碌的时间}{总时间} \]系统吞吐量 单位时间内完成作业的数量 \[系统吞吐量=\frac{总共完成了多少道作业}{总共花了多少时间} \]周转时间 1.周转时间-平均周转时间\[作业周转时间=作业完成时…

​CentOS 7 安装 net-tools.rpm 包步骤详解(附 rpm 命令和 yum 方法)​附安装包

​CentOS 7 安装 net-tools.rpm 包步骤详解(附 rpm 命令和 yum 方法)​附安装包​一、先确认你的系统是 CentOS 7 或 RHEL 7 这个包是专门给 ​CentOS 7​ 或者 ​RHEL 7​(也就是 64 位系统)用的,文件名里的 el7…

青原区城乡建设局门户网站网站建设的系统简介

Kibana是一个开源的分析与可视化平台&#xff0c;设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。是es的可视化客户端之一。 一&#xff1a;下载 https://www.elastic.co/cn/kibana 我的es是elasticsearch-7.10.2版本&#x…

深入解析:【Linux】UDP 网络编程

深入解析:【Linux】UDP 网络编程2025-09-27 11:02 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impor…

浅谈dsu on tree

前言 先学树剖。 讲讲启发式合并,最经典的就是并查集的按秩合并,这里不细讲。 常用的启发式合并就是小集合合并到大集合上,复杂度从 \(O(n^2)\) 优化至 \(O(n \log n)\)。 例题 P3201 [HNOI2009] 梦幻布丁 题目描述…

天河手机网站建设网站建设 讲话

目录 pod启动创建过程 kubelet持续监听的原因 调度概念 调度约束 调度过程 优点 原理 优先级选项 示例 指定调度节点 标签基本操作 获取标签帮助 添加标签&#xff08;Add Labels&#xff09;&#xff1a; 更新标签&#xff08;Update Labels&#xff09; 删除标…

Linux目录下有100百万个文件,如何快速删除

Linux目录下有100百万个文件,如何快速删除Linux目录下有100百万个文件,如何快速删除 利用rsync命令 例:删除/root/files目录下的所有文件ls -l -f /root/files > /tmp/filelist.txt //将目录下的所有文件整理到/…

JavaDay10

Super详解 super注意点: ​ 1.super调用父类的构造方法,必须在构造方法的第一个 ​ 2.super必须只能出现在子类的方法或者构造方法中! ​ 3.super和this不能同时调用构造方法 对比 this: ​ 代表的对象不同: ​ …

29.Linux防火墙管理 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【转】中国信通院《低代码产业发展研究报告(2025年)》核心解读

【转】中国信通院《低代码产业发展研究报告(2025年)》核心解读中国信通院(CAICT)于2025年6月发布的《低代码产业发展研究报告》是中国低代码行业发展的权威性风向标。这份报告不仅全面梳理了低代码市场的最新发展现…

【C++】内存管理 - 指南

【C++】内存管理 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…

昇腾多机推理极速上手:10倍简化的 DeepSeek R1 超大规模模型部署

昇腾多机推理太复杂?易出错?试试 GPUStack在昇腾 NPU 上部署超大规模模型,往往面临一个现实难题:目前主流的官方推理引擎 MindIE 的多机分布式推理虽然性能表现尚可,但配置流程异常复杂。从环境准备、配置初始化到…

python开始exe应用程序初级教程

以下是一个关于如何将Python脚本打包成可执行文件(.exe)的初级教程,使用目前最常用的PyInstaller工具。 准备工作 首先需要安装PyInstaller,打开命令提示符(CMD)或终端,运行以下命令: pip install pyinstaller…

中职校园网站建设建议制作网页的思路

cp -rpf #强行递归复制/etc目录到/mist目录中&#xff0c;并保持源目录的权限等信息不变。 有点类似于打patch&#xff0c;不会改变已有的内容。

凡科可以建设多个网站吗上海手机网站建设电话咨询

用Python解析HTML页面 文章目录 用Python解析HTML页面HTML 页面的结构XPath 解析CSS 选择器解析简单的总结 在前面的课程中&#xff0c;我们讲到了使用 request三方库获取网络资源&#xff0c;还介绍了一些前端的基础知识。接下来&#xff0c;我们继续探索如何解析 HTML 代码&…

网站建设选用平台分析极速蜂app拉新加盟

阿里云服务器是阿里云推出的一种云核算产品&#xff0c;它能够帮助企业和个人快速建立、扩展和管理网络服务。可是&#xff0c;有时候在运用阿里云服务器时&#xff0c;或许会遇到无法装置程序的问题。本文将具体介绍如何处理这个问题。 阿里云服务器无法装置程序或许是由多种原…

版权申请网站宾馆酒店网站建设方案

小伙伴们好久不见&#xff0c;今天我们来聊聊中国 AZURE 的日志分析告警。为什么是中国 AZURE&#xff0c;目前中国 AZURE 的 Monitor 服务和运维相关周围服务和 Global 是有所不同的&#xff0c;所以有些功能和设计不能复制和套用全球版 AZURE 的架构。我们先看一下中国 AZURE…

深入解析:cocos 添加背景,帧动画,贴图

深入解析:cocos 添加背景,帧动画,贴图2025-09-27 10:49 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block…