【Spring】更简单的读取和存储对象
更简单的读取和存储对象
- 一. 存储 Bean 对象
- 1. 前置工作:配置扫描路径
- 2. 添加注解存储 Bean 对象
- @Controller(控制器存储)
- @Service(服务存储)
- @Repository(仓库存储)
- @Component(组件存储)
- @Configuration(配置存储)
- 3. 为什么要这么多类注解?
- 类注解之间的关系
- Bean 命名规则
- 4. 方法注解 @Bean
- 方法注解要配合类注解使用
- 重命名 Bean
- 二. 获取 Bean 对象(对象装配)
- 1. 属性注入
- 2. 构造方法注入
- 3. Setter 注入
- 4. 三种注入优缺点分析
- 5. @Resource:另一种注入关键字
- 6. 同一类型多个 @Bean 报错
在 Spring 中想要更简单的存储和读取对象的核⼼是使⽤注解。
一. 存储 Bean 对象
之前我们存储 Bean 时,需要在 spring-config 中添加⼀⾏ bean 注册内容才⾏:

⽽现在我们只需要⼀个注解就可以替代之前要写的⼀⾏配置,不过在开始存储对象之前,我们先要来点准备⼯作。
1. 前置工作:配置扫描路径
想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中。
在 spring-config.xml 添加如下配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><content:component-scan base-package="com.demo.example"></content:component-scan>
</beans>
<content:component-scan base-package="com.demo.example"></content:component-scan>
上面这行代码指明了组件的扫描路径。即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的。
2. 添加注解存储 Bean 对象
想要将对象存储在 Spring 中,有两种注解类型可以实现:
- 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
- ⽅法注解:@Bean。
@Controller(控制器存储)
@Controller // 将对象存储到 Spring 中
public class UserController {public void sayHi(String name) {System.out.println("Hi," + name);}
}
@Service(服务存储)
@Service
public class UserService {public void sayHi(String name) {System.out.println("Hi," + name);}
}
@Repository(仓库存储)
@Repository
public class UserRepository {public void sayHi(String name) {System.out.println("Hi," + name);}
}
@Component(组件存储)
@Component
public class UserComponent {public void sayHi(String name) {System.out.println("Hi," + name);}
}
@Configuration(配置存储)
@Configuration
public class UserConfiguration {public void sayHi(String name) {System.out.println("Hi," + name);}
}
3. 为什么要这么多类注解?
既然功能是⼀样的,为什么需要这么多的类注解呢?
就是为了让程序员看到类注解之后,就能直接了解当前类的⽤途,⽐如:
- @Controller:表示的是业务逻辑层;
- @Servie:服务层;
- @Repository:持久层;
- @Configuration:配置层。
程序的⼯程分层,调⽤流程如下:

类注解之间的关系
查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的 “子类”
Bean 命名规则
1. 对于类的第一个首字母大写,第二个小写,那么第一个首字母改为小写就是存到容器中的 Bean 的名字。
@Component
public class UserComponent {public void sayHi(String name) {System.out.println("Hi," + name);}
}
UserComponent userComponent = (UserComponent) context.getBean("userComponent");
2. 其他所有情况都是原 Bean 的名字
@Component
public class JDBC {public void sayHi(String name) {System.out.println("Hi," + name);}
}
// JDBC jdbc = (JDBC) context.getBean("jDBC"); // 获取不到JDBC jdbc = (JDBC) context.getBean("JDBC"); // 获取的到
4. 方法注解 @Bean
类注解是添加到某个类上的,⽽⽅法注解是放到某个⽅法上的
方法注解要配合类注解使用
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
只在方法上加 @Bean 注解是不起作用的, 要搭配类注解一起使用。
@Component
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
注意:获取 Bean 时使用对应的方法名获取
User user = (User) context.getBean("user1");
重命名 Bean
可以通过设置 name 属性给 Bean 对象进⾏重命名操作。
@Component
public class Users {@Bean(name = {"u1"})public User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
此时我们使⽤ u1 就可以获取到 User 对象了
User user = (User) context.getBean("u1");System.out.println(user);
这个重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字:
@Component
public class Users {@Bean(name = {"u1", "us1"})public User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
}
并且 name={} 可以省略
@Bean({"u1", "us1"})public User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}
二. 获取 Bean 对象(对象装配)
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。
对象装配(对象注⼊)的实现⽅法以下 3 种:
- 属性注⼊
- 构造⽅法注⼊
- Setter 注⼊
1. 属性注入
举个栗子:使⽤ @Autowired 将 Service 类注⼊到 Controller 类中。
@Controller
public class UserController {// 注⼊⽅法1:属性注⼊@Autowiredprivate UserService userService;public User getUser(Integer id) {// 注入之后直接就可以使用return userService.getUser(id);}
}
2. 构造方法注入
@Controller
public class UserController2 {// 注⼊⽅法2:构造⽅法注⼊private UserService userService;@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}public User getUser(Integer id) {return userService.getUser(id);}
}
如果只有⼀个构造⽅法,那么 @Autowired 注解可以省略。
@Controller
public class UserController2 {// 注⼊⽅法2:构造⽅法注⼊private UserService userService;// 将 Autowired 省略了public UserController2(UserService userService) {this.userService = userService;}public User getUser(Integer id) {return userService.getUser(id);}
}
但是如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法,否则程序会报错。
3. Setter 注入
Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解。
@Controller
public class UserController3 {// 注⼊⽅法3:Setter注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void getUser(Integer id) {userService.sayHi("hello");}
}
4. 三种注入优缺点分析
-
属性注⼊的优点是简洁,使⽤⽅便;
缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,要是想自己 new 一下这个类的对象,那么相关的依赖无法完成注入。
并且不能注入一个不可变的对象(一个 final 修饰的类),因为 Java 中一个 final 对象要么直接赋值要么在构造方法中赋值,不能注入。

-
构造⽅法注⼊是 Spring 推荐的注⼊⽅式,它的缺点是如果有多个注⼊会显得⽐较臃肿,它的优点
可以注入不可变对象;
注入的对象不可变,因为构造方法只随着累加载执行一次;
通用性更好。 -
Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,同样不能注入一个不可变的对象,同时注入的对象可以被修改,因为 Setter 注入只是使用一个普通的方法,其他类也可以多次调用这个方法。所以 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了。
@Controller
public class UserController3 {// 注⼊⽅法3:Setter注⼊private UserService userService;@Autowiredpublic void setUserService1(UserService userService) {this.userService = userService;}public void getUser() {this.setUserService1(null);userService.sayHi("");}
}
5. @Resource:另一种注入关键字
在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊
@Controller
public class UserController {// 注⼊@Resourceprivate UserService userService;public User getUser(Integer id) {return userService.getUser(id);}
}
@Autowired 和 @Resource 的区别
- 出身不同:@Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解;
- 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如name 设置,根据名称获取 Bean。
- @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。
6. 同一类型多个 @Bean 报错
当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:
@Component
public class Users {@Beanpublic User user1() {User user = new User();user.setId(1);user.setName("Java");return user;}@Beanpublic User user2() {User user = new User();user.setId(2);user.setName("MySQL");return user;}
}
在另⼀个类中获取 User 对象
@Controller
public class UserController4 {// 注⼊@Resourceprivate User user;public User getUser() {return user;}
}
代码执行报错,报错的原因是,⾮唯⼀的 Bean 对象

解决同⼀个类型,多个 bean 的解决⽅案有以下两个:
- 使⽤ @Resource(name=“user1”) 定义。
- 使⽤ @Qualifier 注解定义名称。
- 使⽤ @Resource(name=“XXX”)
@Controller
class UserController4 {// 注⼊@Resource(name = "user1")private User user;public User getUser() {return user;}
}
- 使⽤ @Qualifier
@Controller
public class UserController4 {// 注⼊@Autowired@Qualifier(value = "user2")private User user;public User getUser() {return user;}
}
好啦! 以上就是对 Spring 更简单的读取和存储对象的讲解,希望能帮到你 !
评论区欢迎指正 !
相关文章:
【Spring】更简单的读取和存储对象
更简单的读取和存储对象 一. 存储 Bean 对象1. 前置工作:配置扫描路径2. 添加注解存储 Bean 对象Controller(控制器存储)Service(服务存储)Repository(仓库存储)Component(组件存储&…...
【LeetCode热题100】--108.将有序数组转换为二叉搜索树
108.将有序数组转换为二叉搜索树 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 二叉搜索树的中序遍历是升序…...
Redis学习笔记(下):持久化RDB、AOF+主从复制(薪火相传,反客为主,一主多从,哨兵模式)+Redis集群
十一、持久化RDB和AOF 持久化:将数据存入硬盘 11.1 RDB(Redis Database) RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。 备份…...
【智能家居项目】裸机版本——设备子系统(LED Display 风扇)
🐱作者:一只大喵咪1201 🐱专栏:《智能家居项目》 🔥格言:你只管努力,剩下的交给时间! 输入子系统中目前仅实现了按键输入,剩下的网络输入和标准输入在以后会逐步实现&am…...
[Linux]记录plasma-wayland下无法找到HDMI接口显示器的问题解决方案
内核:Linux 6.5.5-arch1-1 Plasma 版本:5.27.8 窗口系统:Wayland 1 问题 在前些时候置入了一块显示器,接口较多,有 HDMI 接口,type-C 接口。在 X11 中可以找到外接显示器,但是卡顿明显…...
【计算机网络】高级IO之select
文章目录 1. 什么是IO?什么是高效 IO? 2. IO的五种模型五种IO模型的概念理解同步IO与异步IO整体理解 3. 阻塞IO4. 非阻塞IOsetnonblock函数为什么非阻塞IO会读取错误?对错误码的进一步判断检测数据没有就绪时,返回做一些其他事情完整代码myt…...
如何设计一个高效的应用缓冲区【一个动态扩容的buffer类】
文章目录 前言一、为什么需要设计应用层缓冲区必须要有 output buffer目的问题output buffer的解决方案: 必须要有 input buffer总结 二、设计要点三、buffer设计思路基础函数关于iovec与readv readfd如何实现动态扩容 问题 前言 在上一个博客,我们介绍…...
图像处理初学者导引---OpenCV 方法演示项目
OpenCV 方法演示项目 项目地址:https://github.com/WangQvQ/opencv-tutorial 项目简介 这个开源项目是一个用于演示 OpenCV 方法的工具,旨在帮助初学者快速理解和掌握 OpenCV 图像处理技术。通过这个项目,你可以轻松地对图像进行各种处理&a…...
管道-匿名管道
一、管道介绍 管道(Pipe)是一种在UNIX和类UNIX系统中用于进程间通信的机制。它允许一个进程的输出直接成为另一个进程的输入,从而实现数据的流动。管道是一种轻量级的通信方式,用于协调不同进程的工作。 1. 创建和使用管道&#…...
【JavaEE基础学习打卡08】JSP之初次认识say hello!
目录 前言一、JSP技术初识1.动态页面2.JSP是什么3.JSP特点有哪些 二、JSP运行环境配置1.JDK安装2.Tomcat安装 三、编写JSP1.我的第一个JSP2.JSP执行过程3.在IDEA中开发JSP 总结 前言 📜 本系列教程适用于JavaWeb初学者、爱好者,小白白。我们的天赋并不高…...
使用序列到序列深度学习方法自动睡眠阶段评分
深度学习方法,用于使用单通道脑电图进行自动睡眠阶段评分。 def build_firstPart_model(input_var,keep_prob_0.5):# List to store the output of each CNNsoutput_conns []######### CNNs with small filter size at the first layer ########## Convolutionnetw…...
【算法】排序——选择排序和交换排序(快速排序)
主页点击直达:个人主页 我的小仓库:代码仓库 C语言偷着笑:C语言专栏 数据结构挨打小记:初阶数据结构专栏 Linux被操作记:Linux专栏 LeetCode刷题掉发记:LeetCode刷题 算法头疼记:算法专栏…...
Docker 容器监控 - Weave Scope
Author:rab 目录 前言一、环境二、部署三、监控3.1 容器监控 - 单 Host3.2 容器监控 - 多 Host 总结 前言 Docker 容器的监控方式有很多,如 cAdvisor、Prometheus 等。今天我们来看看其另一种监控方式 —— Weave Scope,此监控方法似乎用的人…...
Spring Boot集成redis集群拓扑动态刷新
项目场景: Spring Boot集成Redis集群,使用lettuce连接Cluster集群实例。 问题描述 redis其中一个节点挂了之后,springboot集成redis集群配置信息没有及时刷新,出现读取操作报错。 java.lang.IllegalArgumentException: Connec…...
COCI2022-2023#1 Neboderi
P9032 [COCI2022-2023#1] Neboderi 题目大意 有一个长度为 n n n的序列 h i h_i hi,你需要从中选择一个长度大于等于 k k k的子区间 [ l , r ] [l,r] [l,r],使得 g ( h l h l 1 ⋯ h r ) g\times (h_lh_{l1}\cdotsh_r) g(hlhl1⋯hr)最小&…...
由于找不到d3dx9_43.dll无法继续执行此代码怎么解决?全面解析d3dx9_43.dll
在使用计算机过程中,我们可能会遇到各种各样的问题。其中之一就是d3dx9_43.dll文件丢失的问题。这个问题通常会出现在运行某些应用程序或游戏时,导致程序无法正常启动或运行。那么,如何解决这个问题呢?小编将为您提供一些解决方案…...
Linux--网络编程-字节序
进程间的通信: 管道、消息队列、共享内存、信号、信号量。 特点:都依赖于linux内核。 缺陷:无法多机通信。 一、网络编程: 1、地址:基于网络,ip地址端口号。 端口号作用: 一台拥有ip地址的主机…...
python实现http/https拦截
python实现http拦截 前言:为什么要使用http拦截一、技术调研二、技术选择三、使用方法前言:为什么要使用http拦截 大多数爬虫玩家会直接选择API请求数据,但是有的网站需要解决扫码登录、Cookie校验、数字签名等,这种方法实现时间长,难度高。需求里面不需要高并发,有没有…...
农产品团购配送商城小程序的作用是什么
农产品覆盖稻麦油蛋等多种细分类目,各地区经营商家众多,随着人们生活品质提升,对食物的要求也在提升,绿色无污染无激素的农产品往往受到不少人喜爱,而在销售中,也有不少人选择自建商城线上经营。 通过【雨…...
使用van-dialog二次封装微信小程序模态框
由于微信小程序的wx.showModal不支持富文本内容,无法实现更灵活的展示效果,故需要进行二次封装 实现思路:使用van-dialog以及微信小程序的rich-text实现 代码如下: // index.wxml <van-dialoguse-slottitle"提示"s…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
