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

引言

在上一章节中,我们通过设置配置文件的方式简单实现了 Spring 中 Bean 对象的存取,但是相比之下,每次进行对象的注册和获取还是相对麻烦的,那么有没有更简单优雅的方式呢?答案当然是有的:在 Spring 中想要更简单的存储和读取对象的核心是使用注解,本章我们就详细介绍一下在 Spring 中如何使用注解更简单的存取 Bean。

一、存储 Bean 对象

1、配置扫描路径

想要将对象成功的存储到 Spring 中,我们需要配置一下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中。

<?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">

    <!--  配置扫描路径(更简单的存储 Bean 对象)  -->
    <content:component-scan base-package="com.java.demo"></content:component-scan>
    <!--    <bean id="testBean" class="com.java.demo.TestBean"></bean>-->
</beans>

2、类注解存储 Bean

(1)Spring 提供的五大类注解

想要将对象存储在 Spring 中,我们可以采用类注解,Spring 中有五大类注解,虽然这些注解都可以将 对象存储到 Spring 容器中,但是它们存在语义上的差别:

  1. @Controller: 这个注解通常用于标记控制器类,通常用于处理Web应用程序中的请求和响应。

  2. @Service: 这个注解通常用于标记服务类,它表示这个类是一个服务组件,用于执行业务逻辑。

  3. @Repository: 这个注解通常用于标记数据访问层(DAO)的类,表示这个类用于数据库访问。

  4. @Configuration: 这个注解用于标记配置类,通常充当Spring应用程序上下文的配置源。通常与@Bean注解一起使用。

  5. @Component: 这是一个通用的注解,表示一个类是Spring组件。它可以用于任何类,但通常用于没有明确角色的类。其他更具体的注解(如@Controller、@Service、@Repository)实际上是@Component的子类。

其实上面的五大注解,关联着Java项目中的不同层级。对于一个工程化的项目,通常将其划分为不同的层级,进行更精细化的管理,Java中对项目的标准分层规范如下:

(2)使用类注解存储 Bean

使用注解存储 Bean 的方法很简单,只需要在相应的类上添加对应的注解即可。例如将项目中一个表示服务的类添加到 Spring 中:

@Service
public class UserService {
    public void init(){
        System.out.println("this is UserService");
    }
}

(3)类注解存储 Bean 默认命名规则

当我们使用类注解存储 Bean 时,如果我们想要通过 依赖查找 的方式获取到 Bean 对象,那么在 getBean 方法中如何写该 Bean 的名字呢?(在不使用@Service(“name”)的前提下)想要解答这个问题,我们就要取探讨一下在使用类注解存储 Bean 时,它的默认命名规则。

我们通过在 IDEA 中搜索 ““beanName”,可以顺藤摸瓜找到 java.beans 包下的 decapitalize 方法,也就是说 Spring 中使用类注解对 Bean 对象的默认命名使用的是 JDK 中的命名方式:

public static String decapitalize(String name) {
	 if (name == null || name.length() == 0) {
	 	 return name;
	 }
	 // 如果第⼀个字⺟和第⼆个字⺟都为⼤写的情况,是把 bean 的⾸字⺟也⼤写存储了
	 if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
		 Character.isUpperCase(name.charAt(0))){
		 return name;
	 }
	 // 否则就将⾸字⺟⼩写
	 char chars[] = name.toCharArray();
	 chars[0] = Character.toLowerCase(chars[0]);
	 return new String(chars);
 }

通过分析上述源代码,我们可以得出结论:

被注解标注的类,如果类的第一个字母是大写,第二个字母是小写,那么 Bean 的名称就是首字母小写;如果类的第一个字母和第二个字母都是大写,则 Bean 的名称就是原类名。

2、方法注解存储 Bean

方法注解的形式为:@Bean,表示将该方法返回的对象存储到 IoC容器中。

使用示例:

@Configuration
public class ConfigInfo {
    @Bean
    public Config config() {
        // 这里是伪代码
        // ...
        // 获取到 Config 的实例
        return config;
    }
}

使用方法注解存储 Bean 注意事项:

  1. @Bean 注解必须配合五大类注解一起使用。
  2. 使用@Bean 注解存储的 Bean 的默认命名为方法名。

@Bean 注解重命名

  • @Bean(name=“xxx”),简写为@Bean(“xxx”)
  • @Bean(value=“xxx”),简写为@Bean(“xxx”)
  • @Bean(name={“xx”,“xxx”}),简写为@Bean(“xx”,“xxx”)
  • @Bean(value={“xx”,“xxx”}),简写为@Bean(“xx”,“xxx”)

重命名注意事项:当使用 @Bean 重命名后,那么默认使用方法名获取 Bean 对象的方式就不能使用了。

二、获取 Bean 对象

使用注解获取 Bean 对象,是把对象取出来放到某个类中,因此也叫做 对象装配,有时候也叫 对象注入

1、属性注入

假如现在我在 Spring 容器中储存了一个 User 类型的 Bean,那么我们可以使用 @Autowrite 进行属性注入:

public class UserService {
    @Autowired
    private User user;
    public void init(){
        System.out.println(user.toString());
    }
}

属性注入优点:

属性注入最大的优点就是使用简单。

属性注入缺点:

  1. 属性注入无法注入 final 修饰的变量。这是由 java 语法特性决定的,在 Java 中 final 修饰的变量要么直接赋值,要么通过构造方法进行赋值。

  2. 属性注入只适用于 IoC 容器。如果将属性注入的代码移植到其他非 IoC 的框架中,那么代码就无效了。

  3. 属性注入更容易违反单一设计原则。正是因为使用简单,所以滥用它的概率也越大,所以出现违背单一职责原则的概率也越大。

2、Setter 注入

假如现在我在 Spring 容器中储存了一个 User 类型的 Bean,那么我们可以使用 @Autowrite 进行 Setter 注入:

@Service
public class UserService {
	// Setter 注入
    private User user;

    @Autowired
    public void setUser(User user) {
        this.user = user;
    }
    public void init(){
        System.out.println(user.toString());
    }
}

Setter 注入优点:

对于 Setter 本身来说,通常每一个 Setter 只针对一个对象,因此更符合单一设计原则。

Setter 注入缺点:

  1. 由于 Java 语法限制,Setter 注入仍然无法注入一个 final 修饰的变量。
  2. Setter 注入的对象可能被修改。因为 setter 本身是一个方法,也就意味着可能在某些地方被多次调用和修改。

3、构造方法注入

假如现在我在 Spring 容器中储存了一个 User 类型的 Bean,那么我们可以使用 @Autowrite 进行 构造方法注入:

@Service
public class UserService {
    private User user;

    @Autowired
    public UserService(User user) {
        this.user = user;
    }

    public void init(){
        System.out.println(user.toString());
    }
}

:如果当前类中只有一个构造方法时,@Autowrite 可以省略。

构造方法注入优点:

构造方法注入是 Spring 4 之后推荐的注入方式。它主要有如下优点:

  1. 构造方法注入可以注入一个 final 修饰的变量。因为使用构造方法给 final 变量赋值符合 Java 语法规则。
  2. 构造方法注入的对象不会被修改。因为构造方法只会加载一次。
  3. 构造方法注入可以保证注入对象完全初始化。因为依赖对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,会被完全初始化。
  4. 构造方法的通用性更好。构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架。

4、来自JDK的注入关键字:@Resource

使用示例:

@Service
public class UserService {
    @Resource
    private User user1;

    public void init(){
        System.out.println(user1.toString());
    }
}

@Resource 和 @Autowrite 的区别

  1. 出身不同:@Autowired 来自于 Spring,而@Resource 来自于 JDK 的注解。在Java程序中@Resource是先于@Autowrite执行的,因此在专业版的IDEA中,对于@Autowrite来说是不能识别当前类是否存在,因此会报错。
  2. 使用时设置的参数不同:相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。
  3. @Autowired 可用于 Setter 注入、构造函数注入和属性注入,而@Resource 只能用于 Setter 注入和属性注入,不能用于构造函数注入。

特别注意:Spring 框架通过扫描和解析注解来识别和管理Bean对象。当使用@Autowired或@Resource注解进行属性注入时,Spring会在容器中查找匹配的Bean,并将其注入到对应的属性上。如果被注入的属性所属的类没有被Spring容器管理,那么就找不到Spring管理的类,自然类中属性的注入操作就无法执行,可能会导致NullPointerException等异常。

5、如何正确获取 Spring 容器中同类型的 Bean 对象?

在上一章节中我们提到,依赖查找获取 Bean 是依赖于 Bean 的名称的。那么 @Autowrite 的依赖注入流程又是怎样的呢?这里我们先给出结论:

@Autowrite 依赖注入,先根据属性的类型从容器中获取 Bean 对象,如果只获取到一个 Bean 对象,那么直接将此对象注入到当前属性上;如果获取到多个 Bean 对象,会将当前属性名和 Bean 对象名进行匹配,注入名称匹配的 Bean 对象。

根据上述结论,进而引出了另一个问题:如何正确获取 Spring 容器中同类型的 Bean 对象?

为了更好的演示,我们假设储存了两个 User 对象:

@Component
public class Users {
    @Bean("user1")
    public User user(){
        User user = new User();
        user.setName("张三");
        return user;
    }
    @Bean("user2")
    public User user2(){
        User user = new User();
        user.setName("李四");
        return user;
    }
}

当然细心的同学经在上述结论中得到了一种答案:将属性的名字和欲获取的 Bean 名字对应。

@Service
public class UserService {
    @Autowired
    private User user1;
    public void init(){
        System.out.println(user1.toString());
    }
}

上面是一种不错的解决方案,这里再给大家介绍另一种方法:@Autowrite 搭配 @Qualifier

@Service
public class UserService {
    @Autowired
    @Qualifier("user2")
    private User user;
    public void init(){
        System.out.println(user.toString());
    }
}

上面我们了解了@Resource可以设置参数,其中有一个参数就是设置获取 Bean 名称,因此可以使用 @Resource设置name属性(仅适用于属性注入和Setter方法注入)

public class UserService {
	@Resource(name = "user1")
    private User user;
    public void init(){
        System.out.println(user.toString());
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何分离一个要素的shp矢量文件:利用ArcGIS分割工具

下面介绍如何用ArcGIS对含有多个分离区域的一整个面要素进行分割 如下图&#xff0c;现在想要将下方的长形shp提取出来&#xff0c;首先打开shp文件&#xff1a; 右击空白处查看该矢量文件的投影信息&#xff1a; 在文件夹中新建shp文件&#xff0c;设置一样的投影&#xff1a…

MySQL数据库——视图的更新、视图作用以及案例

目录 视图的更新 介绍 示例 视图作用 案例 视图的更新 介绍 要使视图可更新&#xff0c;视图中的行与基础表中的行之间必须存在一对一的关系。 如果视图包含以下任何一项&#xff0c;则该视图不可更新&#xff1a; 聚合函数或窗口函数&#xff08;SUM()、MIN()、MAX()…

蓝桥杯 Java 青蛙过河

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改/**二分法从大&#xff08;n&#xff09;到小找足够小的步长前缀和记录每个位置的前面有的总石头数&#xff08;一个石头表示可以容纳一个青蛙&#xff0c;一位置有多少个石头hi就是多少&#xff09;&…

【动态基础】从暴力递归到动态规划

C面经汇总 系列综述&#xff1a; 目的&#xff1a;本系列是个人整理为了秋招和实习面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡背诵量与深入程度。 来源&#xff1a;材料主要源于算法大神&#xff08;左程云&#xff09;教你从暴力递归到动态规划进行的&#xf…

文件上传预览下载

文件上传的表单必须满足三个条件: 1.表单组件标签只能用:<input type"file" value"xxx">会自动弹框让用户选择文件 2.请求方式只能用post 3.表单编码格式只能用:mutipart/form-data 根据HTTP协议规定,浏览器每次向后台提交参数,都会对参数进行统一…

【软件安装环境配置】vscode 安装界面没有出现安装路径的选择 的解决,以及vscode的删除的问题

由于vscode 没有删除干净&#xff0c;就会出现vscode 安装的时候&#xff0c;没有出现安装路径的界面&#xff0c;所以可以来到vscode的安装路径&#xff0c;点击 unins000.exe 文件就可以 实现将vscode 相关的文件删除&#xff0c; 如果是删除了整个vscode 安装下的文件&…

GPT做SQL查询引擎的自然语言

目录 面向企业查询的生成式人工智能 步骤1&#xff1a;将示例数据转换为单字符字符串 步骤2&#xff1a;为大型语言模型&#xff08;LM&#xff09;创建提示符 步骤3&#xff1a;将数据发送到OpenAI的API 步骤4&#xff1a;执行GPT返回的SQL代码的结果 步骤5(可选)&#…

Webpack简介及打包演示

Webpack 是一个静态模块打包工具&#xff0c;从入口构建依赖图&#xff0c;打包有关的模块&#xff0c;最后用于展示你的内容 静态模块&#xff1a;编写代码过程中的&#xff0c;html&#xff0c;css&#xff0c; js&#xff0c;图片等固定内容的文件 打包过程&#xff0c;注…

智慧巡查平台(Ionic/Vite/Vue3 移动端) 问题记录

目录 1.环境搭建 1.1 安装 node 16 版本 1.2 安装 ionic7 1.3 创建 vue 项目 2.index.html 3.main.ts 3.1 如何默认使用 ios 样式&#xff1f; 3.2 如何使用 ElmentPlus 国际化&#xff1f; 4.router/xxx 5.打包二三事 5.1 添加打包相关文件 5.1.1 .env.developmen…

linux下安装 Chrome 和 chromedriver 以及 selenium webdriver 使用

1 安装 Chrome yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm2 下载 chromedriver # 进入下载目录 cd soft/crawler_tools# 查看chrome 版本号 google-chrome --version# 在chromedriver下载地址中找到对应版本&#xff0c;下载对…

yarn install 这个命令安装如何加速

yarn install 命令用来安装项目依赖&#xff0c;其速度受多种因素影响&#xff0c;如网络速度、npm/yarn包的源服务器、以及本地缓存等。以下是一些可能帮助你加速 yarn install 的方法&#xff1a; 1. 使用国内镜像 如果你在中国&#xff0c;可以使用淘宝的 npm 镜像&#x…

Android 类似淘宝的吸顶特效 NestedScrollView+RecycleView

运行图 布局的设计 要实现上面的效果需要搞定NestedScrollView和RecycleView的滑动冲突。有人要问RecycleView为何要滑动自动撑大不就好了么&#xff1f;这个问题其实对于有限的资源加载来说是很好的解决方案&#xff0c;但是如果涉及到的是图文结合的并且有大批量的数据的时候…

Mac用NTFS文件夹读写NTFS硬盘 NTFS能复制多大的文件

Mac作为一款备受欢迎的计算机操作系统&#xff0c;具备了许多令人惊叹的功能和特性。然而&#xff0c;对于一些Mac用户来说&#xff0c;使用NTFS格式的硬盘可能存在一些疑问。他们可能想知道Mac是否能够读写NTFS格式的硬盘&#xff0c;以及NTFS格式的硬盘是否有文件大小的限制。…

.\missyou-0.0.1-SNAPSHOT.jar中没有主清单属性

引用&#xff1a;https://blog.csdn.net/marypiglwy/article/details/132016171 配置的时候 <skip>true</skip> skip设置为true&#xff0c;跳过了执行插件&#xff0c;&#xff0c; <plugin><groupId>org.springframework.boot</groupId><a…

如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样,蓝牙接近了电脑,电脑自动解锁无需输入开机密码

环境&#xff1a; Win10 专业版 远程解锁 蓝牙解锁小程序 问题描述&#xff1a; 如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样&#xff0c;蓝牙接近了电脑&#xff0c;电脑自动解锁无需输入开机密码 手机不需要拿出来&#xff0c;在口袋里就可以自动解锁&#xff…

vscode json文件添加注释报错

在vscode中创建json文件&#xff0c;想要注释一波时&#xff0c;发现报了个错&#xff1a;Comments are not permitted in JSON. (521)&#xff0c;意思是JSON中不允许注释 以下为解决方法&#xff1a; 在vscode的右下角中找到这个&#xff0c;点击 在出现的弹窗中输入json wit…

【Mybatis源码】XMLConfigBuilder构建器 - 读取XML配置初始化Configuration对象

XMLConfigBuilder是Mybatis中定义的进行构建Configuration对象的类,此类用于读取XML配置文件创建并初始化Configuration对象; 上一篇中我们介绍了XMLConfigBuilder构建器加载XML配置文件以及创建Configuration对象https://blog.csdn.net/m1729339749/article/details/133983…

Linux shell编程学习笔记16:bash中的关联数组

上一节我们探讨了普通的数组&#xff0c;即使用数字下标来索引数组中不同的元素的数组&#xff0c;也可以称之为索引数组。 相比纯粹的数字&#xff0c;字符串不仅能表明含义&#xff0c;也更便于记忆使用&#xff0c;于是就有了关联数组。 一、关联数组概述 bash 从4.0开始支…

【Linux】部署单机OA项目及搭建spa前后端分离项目

目录 部署OA项目 ​编辑 搭建spa前后端分离项目 后端 前端 配置坏境变量 部署OA项目 在虚拟机中&#xff0c;将项目打包成war文件放置到tomcat根目录下的webapps文件目录下 再在主机数据库中连接数据库&#xff0c;并定义数据库名导入相关的表 继续进入tomcat目录下双击点…

香港服务器运行不正常原因简析

​  网站在线业务的部署需要服务器的存在。于我们而言&#xff0c;租用正规服务商(正规机房)的服务器&#xff0c;一般情况下是会很少出现问题。但&#xff0c;要知道&#xff0c;再稳定的服务器也有出现问题的时候&#xff0c;香港服务器也不例外&#xff0c;而且恰恰这个原…