Spring更简单的读取和存储对象

news2025/1/24 5:38:38

文章目录

  • 前言
  • 1、存储 Bean 对象
    • 1.1 前置工作
    • 1.2 添加注解存储 Bean 对象
      • @Controller(控制器存储)
      • @Service (服务存储)
      • @Repository(仓库存储)
      • @Configuration(配置存储)
      • @Component(组件存储)
      • 为什么需要五大类注解以及它们的关系
      • 方法注解 @Bean
  • 2、获取 Bean 对象(对象装配)
    • 2.1 属性注入
    • 2.2 构造方法注入
    • 2.3 Setter 注入
    • 2.4 三种注入方式的区别
    • 2.5 @Autowired 和 @Resource

前言

在 Spring 中想要更简单的存储和读取对象的核心是使用注解

1、存储 Bean 对象

之前我们存储 Bean 时,需要在 spring-config 中添加一行 bean 注册内容才行,并且每个 bean 都要进行注册,例如:

在这里插入图片描述

而现在我们只需要⼀个注解就可以替代之前要写一行配置

1.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.beans"></content:component-scan>	
</beans>

在这里插入图片描述

Spring会以 com.beans 为根路径,进行递归式的扫描,如果类上添加了注解,就会被存储到Spring中。但是如果类添加了注解,却不在配置的扫描路径下,是不会被存储到Spring中的

1.2 添加注解存储 Bean 对象

想要将对象存储在 Spring 中,有两种注解类型可以实现:

  1. 五大类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

@Controller(控制器存储)

使用 @Controller 存储 bean 的代码如下所示:

@Controller
public class UserController {
    public void sayHi() {
        System.out.println("hello Controller");
    }
}

读取 UserController 对象:

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
        UserController userController = context.getBean("userController", UserController.class);
        //调用 bean 方法
        userController.sayHi();
    }
}

在 spring-config 中,我们并没有注册 UserController,因此也就没有 UserController 对应的 name(id),此时,我们在得到 UserController 时,如何知道 UserController 的 name(id)呢?
这里的 name 其实就是 UserController 的小驼峰命名,也就是 userController
如果是 APIController,此时的 name 就是 APIController,和原来的类名保持一致,至于为什么是这样的,可以看一下源码

在这里插入图片描述

@Service (服务存储)

使用 @Service 存储 bean 的代码如下所示:

@Service
public class UserService {
    public void sayHi() {
        System.out.println("hello Service");
    }
}

读取 UserService 对象:

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
        UserService userService = context.getBean("userService", UserService.class);
        //调用 bean 方法
        userService .sayHi();
    }
}

@Repository(仓库存储)

使用 @Repository 存储 bean 的代码如下所示:

@Repository
public class UserRepository {
    public void sayHi() {
        System.out.println("你好 Repository");
    }
}

读取 UserRepository 对象:

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
        UserRepository userRepository = context.getBean("userRepository", UserRepository.class);
        //调用 bean 方法
        userRepository.sayHi();
    }
}

@Configuration(配置存储)

使用 @Configuration 存储 bean 的代码如下所示:

@Configuration
public class UserConfig {
    public void sayHi() {
        System.out.println("你好 Configuration");
    }
}

读取 Configuration 对象:

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
        UserConfiguration userConfiguration = context.getBean("userConfiguration", UserConfiguration.class);
        //调用 bean 方法
        userConfiguration.sayHi();
    }
}

@Component(组件存储)

使用 @Component 存储 bean 的代码如下所示:

@Component
public class UserComponent {
    public void sayHi() {
        System.out.println("你好 Component");
    }
}

读取 UserComponent 对象:

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
        UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
        //调用 bean 方法
        userComponent.sayHi();
    }
}

上述获取 bean 时,除了根据 bean name(id) 和类型获取 bean,还可以根据 bean type 获取 bean,也可以根据 bean name(id) 来获取 bean

为什么需要五大类注解以及它们的关系

通过对这五大类注解的使用,我们发现它们的功能似乎是⼀样的,既然功能是一样的,那为什么需要这么多的类注解呢?

先举个例子:

每个省/市都有自己的车牌号。例如重庆的车牌号就是:渝X:XXXXXX,四川的车牌号是:川X:XXXXXX。甚至⼀个省不同的县区也是不同的,例如重庆,渝A:XXXXXX,表示重庆市区——江南,渝B:XXXXXX,表示重庆市区——江北,渝F:XXXXXX,表示重庆市万州区。
这样做的好处除了可以节约号码之外,更重要的作用是可以直观的标识⼀辆车的归属地

那么为什么需要怎么多的类注解也是相同的原因,让代码的可读性提高,让程序员能够直观的判断当前类的用途。比如:

  • @Controller:表示的是业务逻辑层
  • @Servie:服务层
  • @Repository:持久层
  • @Configuration:配置层

程序的工程分层,调用流程如下:

在这里插入图片描述

在实际的工程中,分层只会比这四层多,不可能会少

如何知道五大类注解是否有关系,只需要查看它们的源码即可

在这里插入图片描述

在这里插入图片描述

通过源码,我们发现 @Controller,@Service,@Repository,@Configuration 都是基于 @Component 实现的,所以可以认为 @Component 是其它四个注解的父类

方法注解 @Bean

@Bean 只能添加到方法上,如果添加到类上,则会显示的报错

先定义一个User类

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + id + ", name=" + name + "}";

    }
}

使用 Bean 注解

@Component
public class UserBeans {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(721);
        user.setName("fl");
        return user;
    }
}

注意:只使用一个 @Bean 是无法将对象存储到容器当中的,必须要还要配合五代类注解才行

获取并使用

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new 
        	ClassPathXmlApplicationContext("spring-config.xml");
		User user = context.getBean("user1", User.class);
		System.out.println(user);
	}
}

在这里插入图片描述

这里是通过 name 来获取 bean 对象的,也可以使用类型来获取,但需要保证这个类型的对象只被注入一次,否则将会报错

在这里插入图片描述

重命名 Bean
可以通过设置 name 属性给 Bean 对象进⾏重命名操作

@Component
public class UserBeans {
    @Bean(name = "u1")
    public User user1() {
        User user = new User();
        user.setId(721);
        user.setName("fl");
        return user;
    }
}

name 属性可以设置多个名字,但需要使用{}括起来,例如:

@Bean(name = {"u1", "u2", "u3"})

此时我们使用 u1 就可以获取到 User 对象了

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到 bean
		User user = (User) context.getBean("u1");
		//3.掉用 bean 方法
		System.out.println(user);
		

@Bean 命名规则:

当没有设置name属性时,那么bean默认的名称就是方法名,当设置了name属性之后,只能通过重命名的name属性对应的值来获取,也就是说重命名之后,再使用方法名就获取不到bean对象。

2、获取 Bean 对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入
对象装配(对象注入 )的实现方法以下 3 种:

  1. 属性注入
  2. 构造方法注入
  3. Setter注入

2.1 属性注入

属性注⼊是使用 @Autowired 或者 @Resource 实现的,将UserBeans类注入到UserController类中。
UserBeans类代码实现:

@Component
public class UserBeans {
    public User user1() {
        User user = new User();
        user.setId(721);
        user.setName("fl");
        return user;
    }

    @Bean
    public User user2() {
        User user = new User();
        user.setId(127);
        user.setName("lf");
        return user;
    }
}

UserController类的代码实现:

@Controller
public class UserController {
    @Autowired
    private User user;
    
    public void sayHi() {
        System.out.println("hello Controller");
    }
    
    @Override
    public String toString() {
        return "UserController{" +
                "user=" + user +
                '}';
    }
}

因为 UserController 类只被注入了一次,因此采用类型来获取 UserController 对象

public class App {
    public static void main(String[] args) {
        //1.先得到上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean对象
        UserController userController = context.getBean(UserController.class);
        //3.调用bean方法
        System.out.println(userController);
    }
}

结果却报错了,原因就是在 UserController 使用 User 对象,会根据名称 user 去找,没有名称为 user 的对象,就会根据类型去找,但是类型为 User 的对象出现了两次(user1,user2),不知道该用哪一个,所以报错了

在这里插入图片描述

只要我们将 user 改为 user1 或者 user2 ,或者将 User 对象只注入一次,就能解决这个问题

还能用 @Resource 设置 name 的方式来重命名注入对象

@Controller
public class UserController {

    @Resource(name = "user1")
    private User user;

    public void sayHi() {
        System.out.println("hello Controller");
    }
} 

在这里插入图片描述

除此之外, 可以使用@ Autowired + @Qualifier来筛选bean 对象

@Controller
public class UserController {

    @Autowired
    @Qualifier("user1")
    private User user;

    public void sayHi() {
        System.out.println("hello Controller");
    }

    @Override
    public String toString() {
        return "UserController{" +
                "user=" + user +
                '}';
    }
}

在这里插入图片描述

@Qualifier中也可以时用键值对的方式来指定对象,例如:@Qualifier(value = “user1”)

2.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,将 Service 类注⼊到 Controller 类中

Service 类的代码实现:

@Service
public class UserService {
    public void sayHi() {
        System.out.println("hello Service");
    }
}

UserController 类的代码实现:

@Controller
public class UserController {
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    public void sayHi() {
        userService.sayHi();
    }
}

调用构造方法时,会直接从 Spring 中取出 userService 对象,赋值给 UserController 类中的userService

构造方法注入,只需要在构造方法前加上 @Autowired 注解即可,如果当前类中只存在一个构造方法,那么 @Autowired 注解可以省略

2.3 Setter 注入

Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set 方法的时候需要加上 @Autowired 注

代码如下:

@Controller
public class UserController {
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void sayHi() {
        userService.sayHi();
    }
}

setter 注入既可以使用 @Autowired 注解,也可以使用 @Resource注解

2.4 三种注入方式的区别

  1. 属性注入:特点写法简单。但是通用性不好,它只能运行在IoC 容器下,如果是非IoC容器就会出现问题
  2. Setter注入:早期Spring版本推荐的写法,Setter注入通用性比构造方法注入差
  3. 构造方法注入:通用性更好、它能确保在使用注入对象之前,此注入对象一定初始化过了。当构造方法注入参数过多时,此时开发者就要检查自己所写的代码是否符合单一设计原则的规范了,此注入方式也是spring 后期版本中推荐的注入方式

2.5 @Autowired 和 @Resource

  1. 出身不同:@Resource 来自JDK (Java亲儿子),@Autowired 是Spring框架提供的
  2. 用法不同:@Autowired支持属性注入、构造方法注入和Setter 注入,而@Resource 不支持构造方法注入
  3. 支持的参数不同:@Resource 支持更多的参数设置,比如name、type 设置,而@Autowired 只支持required参数设置

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

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

相关文章

图书馆管理系统的设计与实现(论文+系统)_kaic

目 录 摘 要 第一章 绪论 1.1本课题研究背景与意义 1.2本课题国内外研究现状 第二章 开发技术介绍 2.1JDK的安装与配置 2.2HTML技术 2.3MySQL数据库管理系统 2.4JDBC的使用 第三章 系统分析 3.1系统的设计要求 3.2系统的设计原则 3.3系统的可行性分析 3.3.1技术可行性 3.3.2经济…

消息队列的概念和原理

消息队列一、使用消息队列的场景1.1、消息队列的异步处理1.2、消息队列的流量控制&#xff08;削峰&#xff09;1.3、消息队列的服务解耦1.4、消息队列的发布订阅1.5、消息队列的高并发缓冲二、消息队列的基本概念和原理2.1、消息的生产者和消费者2.2、Broker2.3、点对点消息队…

【Linux修炼】9.环境变量

每一个不曾起舞的日子&#xff0c;都是对生命的辜负。 环境变量本节目标1. 环境变量1.1 环境变量的概念1.2 环境变量PATH1.3 其他常见环境变量2. 和环境变量相关的命令2.1 env 命令2.2 export命令2.3 set命令2.4 unset命令3. 环境变量的意义4. 命令行参数4.1 什么是命令行参数&…

Array reduce() 如何计算元素内数值总合,计算总合

Array reduce() 如何计算元素内数值总合&#xff0c;计算总合 一、需求 有时候我们需要计算一个数组中所有元素的总合&#xff0c;这个数组可能是组 Number 类型&#xff0c;也可能是 Object 类型&#xff0c;像这样&#xff1a; const tempArray [2,3,4,6,456,89,24] // 或…

1.1MQ的基本概念,优劣势介绍及 RabbitMQ简介

1.MQ的基本概念 1.1 MQ概述 M Q 全称 Message Queue 消息队列&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间的通信。 1.2 MQ 的优势 1.2.1应用解耦 当订单系统强依赖库存系统&#xff0c;支付系统&#xff0c;物流系统等&#xff0c;若其中一个系…

Lambda求和函数在excel上的应用

目录 一、Lambda函数 二、Lambda求和函数 三 、实际表格运用 四、计算结果 一、Lambda函数 Lambda函数是使用lambda运算符创建的&#xff0c;其语法如下&#xff1a; 语法&#xff1a; lambda 参数&#xff1a;表达式 Python lambda函数可以包含任意多的参数&#xff0c;但…

Js逆向教程-16极验滑块 找到w加密位置

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; Js逆向教程-16极验滑块 找到w加密位置 一、如何下第一个断点 https://www.geetest.com/demo/slide-float.html 接口有多个w参数&…

springboot+vue 任课教师考评评价系统 Java 前后端分离

随着我国教育改革的发展&#xff0c;各大高校的大学生数量也在不断的增加&#xff0c;相对应如何去评价教学的质量问题也是很多高校一直以来所关注的内容。只有有了一个好的教学评价制度才能够让各大高校的教学质量稳步提升&#xff0c;本系统就是这样一个根据各项指标对教学质…

day77:注解、自定义注解、元注解

一、注解 1.什么是注解 注解是对程序进行标注和解释 2.常用注解 Override 描述子类重写父类的方法Deprecated 描述此方法已过时SuppressWarnings 压制警告 3.图解 4.注解与注释的区别 注解&#xff1a;给编译器看的&#xff0c;让虚拟机知道程序的特殊功能注…

【吴恩达机器学习笔记】

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

PostgreSQL 同步复制原理解析

背景 Postgresql 在主备架构的场景下&#xff0c;支持同步流复制功能。本文将以一主一备架构为例&#xff0c;介绍同步流复制&#xff08;同步备机&#xff09;的工作方式以及内核代码的相关原理。 配置同步备机 工欲善其事&#xff0c;必先利其器。我们现简单的配置一个同步…

微信小程序图书管理系统

目 录 摘 要 I Abstract II 目 录 V 1 绪论 1 1.1研究背景 1 1.2研究课题和意义 2 1.3研究内容和论文结构 3 2 移动网络环境下图书管理系统的现状分析 4 2.1移动网络环境下图书管理系统的特点 4 2.2当前国内外移动网络环境下图书管理系统的现状 7 2.3微信给移动网络环境下图书管…

遥感技术及高分遥感影像在地震中的应用及高分二号获取

长期以来&#xff0c;地震预报监测、灾害调查、灾情信息获取主要依靠实地勘测手段&#xff0c;其获取的数据精度和置信度虽然较高&#xff0c;但存在工作量大、效率低、费用高和信息不直观等缺点。遥感技术手段可在一定程度上克服传统实地勘测手段的缺点&#xff0c;并具有其他…

我参加第七届NVIDIA Sky Hackathon——训练ASR模型

如何从0开始训练自己的ASR模型 第一步 获取NGC密钥 第二步 配置Ubuntu22.04的运行环境 第三步 开始训练ASR模型 文章目录如何从0开始训练自己的ASR模型前言一、获取NGC密钥二、配置Ubuntu22.04的运行环境1.安装 NVIDIA 驱动 460 以上版本2.安装 docker 与 nvidia-docker23.安装…

iClient for Leaflet实现动态绘圆的几何查询

作者&#xff1a;ls 【目录】 背景前期准备呈现效果实现过程完整代码 【背景】 几何查询是WebGIS项目中一项比较常用的功能&#xff0c;SuperMap iClient 产品支持的几何对象类型众多&#xff0c;能够满足用户的许多需求。 近期遇到许多小伙伴反应&#xff0c;绘制圆形进行…

spring复习03,注解配置管理bean

spring复习03,注解配置管理bean注解的配置1.标识组件的常用注解&#xff1a;2.扫描组件&#xff1a;3.基于注解的自动装配&#xff1a;4.使用注解以后:基于注解自动装配的小例子1.dao层&#xff1a;2.service层&#xff1a;3.controller层&#xff1a;4.spring配置文件5.测试输…

Python控制程控电源

文章目录前言一、环境搭建二、使用步骤三、执行结果总结前言 本文章主要是记录汽车电子或嵌入式设备自动化测试中&#xff0c;部分场景需要控制被测设备的供电电源&#xff0c;以下就以常见的艾德克斯程控电源为例&#xff0c;分享如何通过Python来控制程控电源。 一、环境搭建…

Java字符串(String类)

目录 &#x1f6f4;一.认识String类 &#x1f6f4;二.String类的使用 &#x1f384;2.1构造字符串 &#x1f384;2.2字符串长度 &#x1f384;2.3String对象的比较 &#x1f384;2.4字符串查找 &#x1f45c;charAt方法 &#x1f45c;indexOf方法 &#x1f45c;lastI…

浅谈 Class.forName() 的用法

目录 什么是class对象 获得class对象的三种方法 class的作用和方法 Class.forName()用法 什么时候用Class.forName()&#xff1f; newInstance和new关键字的区别 应用问题解析 情景一&#xff1a;载入数据库驱动的时候 情景二&#xff1a;使用AIDL与电话管理Servic进行通…

[Spring Boot 5]安全管理

本文介绍了Spring Security 以及Shiro 在Spring Boot中的使用&#xff0c;对于Spring Security 有基于传统认证方式的Session认证&#xff0c;也有使用OAuth 协议的认证。一般来说&#xff0c;传统的Web架构中&#xff0c;使用Session 认证更加快速&#xff0c;但是&#xff0c…