Spring 用注解更简单存取对象

news2024/11/16 8:44:02

Spring 用注解更简单存取对象

​ 上一篇文章是最原始的创建使用,这篇主要是讲 Spring 更简单的存储和读取对象的核心是使用注解 ,也是日常生活企业用的最多的方法 “注解” 所以这篇的内容是很重要的 !!!

文章目录

  • Spring 用注解更简单存取对象
    • 一、更简单的存储 Bean 对象
      • 1.1 前置工作
    • 二、添加注解存储 Spring 中(存)
      • 2.1、类注解
        • 2.1.1、@Controller
        • 2.1.2、@Service
        • 2.1.3、@Repository
        • 2.1.4、@Component
        • 2.1.5、@Configuration
      • 2.2、类注解的区别
        • 2.2.1、类注解的关系
      • 2.3、方法注解
        • 2.3.1、@Bean
          • 2.3.1.1、方法注解要配合5大类注解一起使用
          • 2.3.1.2、@Bean 重命名
    • 三、Bean(对象) 的命名
    • 四、获取 Bean 对象 (对象装配)
      • @Autowired
      • 4.1、属性注入(企业、个人 常用)
      • 4.2、构造方法注入(官方推荐)
      • 4.3、Setter 注入
      • 4.4、三个注入的区别对比 (面试)
      • @Resource 另一种注入的方式

一、更简单的存储 Bean 对象

1.1 前置工作

​ 需要再 Spring 的配置文件中设置组件 Component 的根路径

<?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注解扫描的根路径(方面后面更简单存储对象到spring容器)-->
    <content:component-scan base-package="根路径"></content:component-scan>
</beans>

这是很重要的一步,在 resources 包下创建 xml 文件来配置 Spring 信息。这里面主要加了一个 component 扫描路径代码。

<content:component-scan base-package="组件扫描根路径"></content:component-scan>

❓❓❓问题来了,为什么要这要设置,不能想以前添加 bean 对象吗?

​ 使用扫描包根路径的作用:这个配置信息可以扫描你设置的根路径以下的类,扫描是否添加了注解,把添加了注解的类存入 spring 容器里面,不加根路径范围全部扫描所有文件的话增加工作量效率不高吃性能。

注意只有在根路径里面添加了注解才会被添加进 spring 里面,在根路径意外的即使添加了注解是不会被添加进spring 里的

​ 使用扫描包路径的优势:

  • 不用再每次注册内容的使用都在配置文件中添加 bean 对象,之后做项目的时候每次注册bean对象会增加工作量相率正确性也不高。扫描包配置添加注解直接存入 spring 里面 更方便快捷提升效率提高性能
  • 配置文件信息代码少,不复杂,只关注根路径就行
  • 与注解搭配使用,目前企业都主要是用注解,而不是用的原始方法

在这里插入图片描述

二、添加注解存储 Spring 中(存)

2.1、类注解

2.1.1、@Controller

import org.springframework.stereotype.Controller;

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

@Controller 注解就相当于在spring 容器里面存储了 bean 对象:

<bean id="userController" class="com.yuanye.beans.userController"></bean>

@Controller 注解在spring启动的时候就把当前的对象存储在容器里面了。获取对象的方法还是老三步骤:

1、得到 Spring 上下文

2、使用上下文对象获得一个 bean

3、使用 bean

具体操作步骤可以看这篇文章 Spring核心 and 创建使用

2.1.2、@Service

将对象存储在 spring 容器中

import org.springframework.stereotype.Service;

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

@Service 注解就相当于在spring 容器里面存储了 bean 对象:

<bean id="UserService" class="com.yuanye.beans.UserService"></bean>

2.1.3、@Repository

将对象存储在 spring 容器中

import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {
    public void sayhi() {
        System.out.println("hi UserRepository");
    }
}

与上面的方法是一样,不再赘述。

2.1.4、@Component

以上。

import org.springframework.stereotype.Component;

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

2.1.5、@Configuration

同上。

import org.springframework.context.annotation.Configuration;


@Configuration
public class UserConfiguration {
    public void sayHi() {
        System.out.println("hi,UserConfiguration");
    }
}

2.2、类注解的区别

❓❓❓问题:尽然他们的功能都是一样的,那么他们究竟是有什么区别尼??

​ 主要还是用来处理业务逻辑相关,让程序员一看使用某注解就明白某类在业务功能上面的用途。

  • @Controller:表示业务逻辑层(首先与前端交互验证)
  • @Service:表示服务层
  • @Repository:持久层
  • @Configuration:配置层
  • @Component:实体类

程序的工程分层图如下:

image-20230709000704200

这张图也详细说明了每个注解的作用。

2.2.1、类注解的关系

​ 从源代码来说,@Controller / @Service / @Repository / @Configuration 等注解他们都有@Component的注解。

image-20230709001740243

结论:@Controller / @Service / @Repository / @Configuration 等注解他们本身属于是 @Component 的 子类

2.3、方法注解

​ 方法注解就是放在方法上面的注解

2.3.1、@Bean

目标:@Bean 将当前方法返回的对象存入到 Spring 容器中

代码实现:

import com.yuanye.model.UserInfo;
import org.springframework.context.annotation.Bean;

public class UserBeans {
    @Bean
    public UserInfo getUser() { // 方法名就是 bean name
        UserInfo userInfo = new UserInfo();// 伪代码
        userInfo.setId(1);
        userInfo.setName("鸢也");
        userInfo.setPassword("123456");
        return userInfo;
    }
}

这是在 Spring 中注册方法,获取这个方法还是三步骤,只不过 bean name 是方法的名字

UserInfo userInfo = applicationContext.getBean("getUser",UserInfo.class);

但是这样写程序会报错:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException:

❓❓❓这又是为什么尼??

2.3.1.1、方法注解要配合5大类注解一起使用

答案就是方法注解要配合类注解一起使用。这是 spring 设计之初就是这样设计的。

❓❓❓为何要这样设计???

原因是出于性能的考量:相当于就是加一个范围,不加范围一个项目可能有成千上百个方法,如果都要扫描一遍检查是否要将返回值存储到 Spring 里面中,那么代价太大,效率低,成本高。故要 方法注解搭配类注解 来实现对象的托管。

正确代码:

import com.yuanye.model.UserInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean
    public UserInfo getUser() { // 方法名就是 bean name
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("鸢也");
        userInfo.setPassword("123456");
        return userInfo;
    }
}
2.3.1.2、@Bean 重命名

​ @Bean 有一个特性 ,它可以重命名 id name。

  • 可以给当前对象指定多个名称
  • 使用多给名称获取的对象是同一个
  • 使用了重命名不可再使用原方法名来作为 id name(原方法id name 就会得不到对象)
import com.yuanye.model.UserInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class UserBeans {
    @Bean(name = {"user","userfo"}) //@Bean("user")
    public UserInfo getUser() { // getUser 已经无法再使用,得不到对象
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("鸢也");
        userInfo.setPassword("123456");
        return userInfo;
    }
}

​ 当他重命名的时候,获取 bean id 就是用的重命名,更方便操作。以上两种写法都可以,如果是一个重命名参数格式 @Bean("user") ,多个重命名参数格式 @Bean(name = {"user","userfo"})

注意:使用了重命名就只能使用重命名之后 老方法获取对象 name 不可再次使用 原方法名,因为程序会报错,就拿不到当前对象

三、Bean(对象) 的命名

​ 首先查看源码:(一般用在类中的命名方式)通常使用在 bean id(name) 上面

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        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);
    }

​ 在第二个if判断语句中,可以看出某类如果第一个字符和第二个字符是大写,那么就返回原来的名字就不用修改;

​ 第10行代码中,如果第一个字符是大写,第二个字符是小写,那么就要修改 bean 的名称,就要把第一个字母改为小写即可。

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

@Autowired

​ 获取 bean 对象也叫做对象装配 ,是把对象取出来放到某个类中,有时候也叫作 对象注入 (DI:Dependency Injection)。

对象注入的方式有3种:

  • 属性注入 (企业、个人 常用)
  • 构造方法注入 (官方推荐)
  • Setter 注入

注入又是怎么样理解?

​ 程序运行期间动态的将当前类需要的依赖类,比如说A类里面需要调用B的方法,那么A类就需要依赖B类,需要B对象。那么在A类里面动态的加载B类过程就叫做“注入”。

说白了就是在 Spring 当中把对象拿进当前的对象

​ 之前我们都是用的旧方法的三部曲:

1、得到 Spring 上下文

2、使用上下文对象获得一个 bean

3、使用 bean

现在也是可以用一个注解就搞定的。

4.1、属性注入(企业、个人 常用)

​ 使用属性注入的方式获得对象,获取对象的注解为 @Autowired ,接下来我们用 @Service 注入到 @Controller的方法中

@Controller代码实现如下:

@Controller
public class ArtController {
    @Autowired
    private ArtService artService;

    public void addArt(String title, String content) {
        if (title!=null && content!=null &&
                !title.equals("") && !content.equals("")) {
            // 满足校验条件就 执行 Service
            artService.addArt(title,content);//注入了ArtService类就可以使用里面的方法了
        }else {
            System.out.println("添加文章失败,前端传递了非法参数");
        }
    }
}

@Serviced代码如下:

@Service
public class ArtService {
    public void addArt(String title,String content) {
        System.out.println("执行了文章的 Service 方法:" +
                ""+title+" | "+content);
    }
}
@Autowired
private ArtService artService;

这段代码就是属性注入的代码,动态的把 ArtService 这个对象注入进了 ArtController 类里面。

运行顺序:先使用类型进行查询,如果在 Spring 中查询到了同类型的对象就直接返回;否则使用类名称进行查询,如果两个都查询不到,那么注入失败,否则就是成功。属性注入意思就说你申请的属性中类和类名都是可以在 spring 里面找的,类找不到就换成类名找 。

4.2、构造方法注入(官方推荐)

​ 当一个类中只用一个构造方法的时候,此时注解 @Autowired 可以省略,当有多个构造方法的时候 @Autowired 不可以省略。当有多个构造方法的时候,需要注入那个类就在构造方法钱加上注解 @Autowired

image-20230710203446560

​ 这是官方推荐的方法,有点是他的通用性,移植性好,缺点是多个注入代码会显得比较的臃肿,当然也可以更改设计模式让代码不会太臃肿。

4.3、Setter 注入

​ setter注入里面的注解是千万不能省略的,不管是一个还是多个 setter 方法都是不能省略的,这点与构造方法注入要分清楚。

private ArtService artService;
@Autowired
public void setArtService(ArtService artService) {
    this.artService = artService;
}

​ 这里主要是创建一个 setter 方法 来注入,大差不差与构造方法差不多,只不过 注解 需要注意一下。


4.4、三个注入的区别对比 (面试)

1、属性注入:优点他的方式是最简单,代码最少得;缺点:此种写法只适用于 IoC 容器,非 IoC 容器不能识别。(但是企业,个人经常用这种方法)

2、构造方法注入:是官方推荐的方案。优点:通用性比较好,代码移植性高;缺点:代码比较多,看起来比较臃肿。(官方推荐)

3、Setter 注入:是 Spring 早期版本推荐的注入方式,通用性好,现在是推荐使用构造方法注入也是默认的注入方式。(早期版本推荐)


@Resource 另一种注入的方式

​ @Resource 的功能是与 @Autowired 的功能是一致的,但也是有区别。

在这里插入图片描述

根据上面的图片

  • 第一个区别就是设置的参数不同,使用 @Autowired 只能设置一个属性,而@Resource 却可以设置多个参数。
  • 他们的出生是不同的:@Autowired 来自于 Spring 框架,@Resource 来自于 JDK。
  • 修饰的对象不同:@Autowired 可以用于属性注入,构造方法注入,Setter 注入,@Resource只能用在 属性注入和 Setter 注入,不能用于构造方法注入。

对于多种参数的情况,Spring 也是想了办法解决的。

针对一个对象类型被 Spring 注入多个,我们可以使用 @Autowired + @Qualifier .

格式:

1、@Resource(name = “”)

@Resource(name = "user1")
private UserInfo userInfo;

2、@Autowired + @Qualifier

@Autowired
@Qualifier("user1")//@Qualifier(value = "user1")
private UserInfo userInfo;

总结:

1、将对象存储在 Spring 中:

  • 使用类注解 @Controller / @Service / @Repository / @Configuration /@Component [注意他们注解之间的关系]
  • 使用方法注解 @Bean 【必须和5大注解类一起使用】

2、从 Spring 中获取对象:

  • 属性注入
  • 构造方法注入
  • Setter 注入

4、注入的关键字:

  • @Autowired
  • @Resource

两个关键字之间的区别:出生不同;参数设置不同,@Autowired支持一个属性参数,@Resource支持多个参数设置

5、解决一个对象类型被 Spring 注入多个 Bean 的方法

  • 使用@Resource(name = “”)
  • 使用@Autowired+@Qualifier(“”)

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

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

相关文章

基础篇--单片机简介

单片机简介 视频教程 单片机是什么 单片机&#xff1a;Single-Chip Microcomputer 单片微型计算机&#xff0c;是一种集成电路芯片 单片机有什么用&#xff1f; 单片机发展历程 单片机发展超势 CISC Vs RISC CISC和RISC举例 https://wenku.baidu.com/view/b074b0ed998fcc22b…

浅谈Acrel-2000电力监控系统在配电工程中的应用 安科瑞 许敏

摘 要&#xff1a;随着社会经济的快速发展&#xff0c;我国变电站正朝着现代化的方向不断发展&#xff0c;自动化设备以及继电保护装置凭借自身优异性能而获得广泛应用。本文介绍的AM5SE系列的微机保护装置&#xff0c;可以针对中原科技城智慧能源配电工程中不同保护对象提供对…

全志f1c200s嵌入式驱动开发(原理图)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 熟悉全志soc的同学都知道,除了v3s之外,其实还有很多性价比很高的soc。这里面就包含了f1c200s。之前的v3s,也就是我们所说的licheepi上面的soc,反响很不错。后期又出了一个liche…

【数据结构与算法】力扣:二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 示例 2&#xff1a; 输入&a…

纷享销客携手新奥动力,赋能能源装备制造业企业增长再提速

近日&#xff0c;纷享销客与新奥能源动力科技&#xff08;上海&#xff09;有限公司&#xff08;以下简称&#xff1a;新奥动力&#xff09;售后数字化平台项目启动仪式在上海顺利召开&#xff0c;新奥动力和纷享销客双方多位高管共同出席了当天的启动会&#xff0c;双方就CRM建…

leetcode链表刷题记录

题单&#xff1a; 一&#xff0c;移除链表元素 题目描述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 题目接口&#xff1a; /*** Definition for singly-linked list.* struct Lis…

轻量化与强度:挑选骑行爱车的科学平衡之道

在自行车运动的大家庭中&#xff0c;挑选一辆既轻量化又强度又够的自行车是一项关键的任务。那么&#xff0c;如何在轻量化与强度的矛盾中寻找这个科学的平衡点呢&#xff1f;让我们跟随本文&#xff0c;一起探讨如何挑选骑行爱车的科学之道。 首先&#xff0c;我们需要明确&am…

第4章 SSD核心技术:FTL 4.3-4.5

4.3 垃圾回收 4.3.1 垃圾回收原理 WA&#xff08;Write Amplification&#xff09;&#xff0c;即写放大。 OP&#xff08;Over Provisioning&#xff09;&#xff0c;即预留空间。 4.3.2 写放大 对于空盘来说&#xff08;未触发GC&#xff09;&#xff0c;写放大一般为1&…

基于DarkFace数据集的高精度人脸检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于DarkFace数据集的高精度人脸检测系统可用于日常生活中来检测与定位人脸目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的人脸目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练…

volatile 原理

volatile 的底层实现原理是内存屏障&#xff0c;Memory Barrier&#xff08;Memory Fence&#xff09; 对 volatile 变量的写指令后会加入写屏障对 volatile 变量的读指令前会加入读屏障 如何保证可见性 写屏障&#xff08;sfence&#xff09;保证在该屏障之前的&#xff0c…

液晶仪表业务去年赚了4个亿,又一家汽车电子厂商冲刺IPO

液晶仪表&#xff0c;有多赚钱&#xff1f; 本周&#xff0c;随着天有为电子首次对外发布IPO招股说明书&#xff0c;这家专注于电子式组合仪表、全液晶组合仪表和双联屏仪表等产品的传统汽车仪表企业&#xff0c;揭开了过去几年的财务数据。 作为一家传统汽车仪表转型升级的典…

sqlserver导入外部数据文件

1、外部数据文件存为txt格式&#xff0c;可以带中文标题保存。 2、登录链接数据库服务器&#xff0c;选择任意一个数据库右键-任务-导入数据-数据源&#xff1a;选择Flat File Sourse 平面文件.-文件名&#xff1a;选择文件路径-浏览一下列是否对应上。-下一步-目标&#xff1a…

WebStorm配置代码模板【以vue模板为例,提供vue代码模板】

配置过程 引言 为了便于开发&#xff0c;提高生产效率&#xff0c;我们通常会复制粘贴一些共同代码&#xff0c;在WebStorm中&#xff0c;可以将这些共同代码制作成模板&#xff0c;在使用的时候&#xff0c;只需要输入关键字点击按键即可将模板的代码粘贴到代码文件中&#…

免费申域名

申请地址&#xff1a;https://nic.eu.org/ 英国人地址生成器&#xff1a;https://www.shenfendaquan.com/Index/index/ying_guo_shen_fen_sheng_cheng 1、注册 填写注册信息 进入注册页面&#xff0c;输入注册信息。这里我们打开英国人地址生成器&#xff0c;用英国的信息注…

数据库应用:MySQL数据库使用与管理

目录 一、理论 1.MySQL基本操作 2.数据类型 2.使用MySQL数据库 二、实验 1.查看数据库结构 2.创建及删除库和表 3.管理表中的数据记录 4.修改表名和表结构 5.查看、修改字符集 三、问题 1.表导入新记录报错 四、总结 一、理论 1.MySQL基本操作 &#xff08;1&…

【sql注入-延时注入】sleep()、benchmark()函数 延时注入

目录 sleep()、benchmark()延时注入 一、语法介绍&#xff1a; 二、延时注入 三、不同数据库 网络安全小圈子 sleep()、benchmark()延时注入 一、语法介绍&#xff1a; 版本&#xff1a; sleep() MySQL>5.7.8 benchmark() MySQL>5.7.5 语法&#xff1a; 使用…

孤立随机森林(Isolation Forest)(Python实现)

目录 1 简介 2 孤立随机森林算法 2.1 算法概述 2.2 原理介绍 2.3 算法步骤 3 参数讲解 4 Python代码实现 5 结果 1 简介 孤立森林&#xff08;isolation Forest&#xff09;是一种高效的异常检测算法&#xff0c;它和随机森林类似&#xff0c;但每次选择划分属性和划分点&…

Linux5.95 ELK企业级日志分析系统

文章目录 计算机系统5G云计算第四章 LINUX ELK 企业级日志分析系统一、ELK 概述1.ELK 简介1&#xff09;ElasticSearch2&#xff09;Kiabana3&#xff09;Logstash4&#xff09;可以添加的其它组件&#xff1a;Filebeat5&#xff09;缓存/消息队列&#xff08;redis、kafka、Ra…

Ubuntu 18.04 下 uhd+gnuradio 安装指南,国产B210

安装ubutnu18.04&#xff0c;换源&#xff0c;apt-get update 一、虚拟机设置以及安装low-latency内核 给虚拟机分配尽可能多的cpu及内存。在USB控制器选项中&#xff0c;将USB兼容性设置为USB 3.1。 USRP B210需要用USB线连接到电脑的USB 3.0/3.1接口上&#xff0c;实现供电…

Melon库运用——栈篇

头文件片段 // mln_stack.htypedef struct mln_stack_node_s {void *data;struct mln_stack_node_s *prev;struct mln_stack_node_s *next; } mln_stack_node_t;typedef struct {mln_stack_node_t *bottom;mln_stack_node_t *top;mln_stac…