【Spring】Spring更简单的读取和存储对象---使用注解

news2024/10/6 5:59:12

目录

1.Spring的存储对象------存储Bean对象

1.前置工作,配置扫描路径

2.添加注解存储Bean对象

1.@Controller(控制器存储)

2.@service(服务存储)

3.@Repository(仓库存储)

4.@Component(组件存储)

5.@Configuration(配置存储)

3.为什么这么多类注解

1.类注解之间的关系

4.方法注解@Bean

1.方法注解要搭配类注解使用

2.重命名Bean

2.Spring的读取------获取Bean对象(对象装配)

1.属性注入

2.构造方法注入

3.Setter注入

4.三种注入方法的优缺点

 5.@Resource:另一种注入关键字

@Resource和@Autowired的区别

6.同一类型多个@Bean报错

1.现象

 2.报错处理

使⽤ @Resource(name="xxx")

使⽤ @Qualifier


在上一篇文章中实现了基本的Spring读取和存储对象。但在操作的过程中我们发现读取和存储对象并没有想象中的那么“简单”。

所以接下来我们要讲解更加简单的操作 Bean 对象的⽅法。其核心就是,使用注解

1.Spring的存储对象------存储Bean对象

之前我们存储 Bean 时,需要在 spring-config 中添加⼀⾏ bean 注册内容才⾏,如下图所示:

⽽现在我们只需要⼀个注解就可以替代之前要写⼀⾏配置的尴尬了。

类注解规则:1.类名前两位均为大写时,返回自身name

                  2.否则,首字母小写

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

其中标红的一行为注册扫描的包,如下图所示:

注意:即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到Spring中的。

2.添加注解存储Bean对象

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

1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。

2. ⽅法注解:@Bean。

1.@Controller(控制器存储)

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

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

在App中读取上面的UserController对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserController userController=(UserController) context.getBean("userController");
        userController.sayHi();
    }
}

运行结果:

这里并没有在spring-config.xml中添加id,但是依旧能正确运行。是因为@Controller注解自动的起到了一个id的作用。作用与如下代码一致:

    <bean id="userController" class="org.example.UserController"></bean>

2.@service(服务存储)

使用@service存储Bean的代码如下所示:

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

在App中读取上面的UserService对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserService userService=(UserService) context.getBean("userService");
        userService.doService();
    }
}

3.@Repository(仓库存储)

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

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

在App中读取上面的UserRepository对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserRepository userRepository=(UserRepository) context.getBean("userRepository");
        userRepository.sayHi();
    }
}

4.@Component(组件存储)

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

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

在App中读取上面的UserComponent对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserComponent userComponent=(UserComponent) context.getBean("userComponent");
        userComponent.sayHi();
    }
}

5.@Configuration(配置存储)

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

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

在App中读取上面的UserConfiguration对象:

public class App {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        UserConfiguration userConfiguration=(UserConfiguration) context.getBean("userConfiguration");
        userConfiguration.doConfiguration();
    }
}

3.为什么这么多类注解

由以上对每个注解的介绍,可以看出,这些注解的功能都是一样的,那么为什么需要这么多类注解呢?

其目的就是让程序员看到类注解之后,就能直接了解当前类的用途。

@Controller:表示业务逻辑层,通常是指程序的入口,比如:参数校验,参数类型转换等前置处理工作。

@Service:服务层,一般写业务代码,服务编排,比如:调用DB,调用第三方接口。

@Repository:持久层,仓库,通常指DB操作相关的代码。(通常放在DAO层下面)

@Component:其它的对象。

@Configuration:配置层。

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

1.类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

 其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“子类”。

4.方法注解@Bean

1.方法注解要搭配类注解使用

在 Spring 框架的设计中,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:

@Configuration
public class BeanConfig {
    @Bean
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

注意:@Bean对应生产的bean名称是方法名

2.重命名Bean

可以通过设置name属性给Bean对象进行重命名操作,如下对象所示:

@Configuration
public class BeanConfig {
    @Bean(name={"wen","user"})
    public User user() {
        User user=new User();
        user.setName("温温");
        user.setAge(18);
        return user;
    }
}

此时使用wen和user都可以获取到User对象了:

        User user=(User) context.getBean("wen");
        System.out.println(user.getName());

2.Spring的读取------获取Bean对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊

对象装配(对象注⼊)的实现⽅法以下 3 种:

1. 属性注⼊

2. 构造⽅法注⼊

3. Setter 注⼊

1.属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。

Service类的代码如下:

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

Controller类的实现代码如下:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    public void sayHi(){
        userService.doService();
        System.out.println("hi,userController~");
    }
}

最终结果如下:

2.构造方法注入

构造方法注入是在类的构造方法中实现注入,实现代码如下:

@Controller
public class UserController2 {
    private UserService us;
    public UserController2(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

注意:1.如果只有一个构造方法,那么@Autowired可以省略

           2.如果有多个构造方法,那么需要添加上@Autowired来明确指定到底使用哪个构造方法,否则程序会报错。

3.Setter注入

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

解,如下代码所示:

@Controller
public class UserController1 {
    private UserService us;
    @Autowired
    public void setUs(UserService us) {
        this.us = us;
    }
    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

4.三种注入方法的优缺点

优点缺点
属性注入简介,使用方便
1.是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)
2.不能注入一个final修饰的属性
构造方法注入(
 Spring 推荐

1.可以注入final修饰的属性

2.注入的对象不会被修改

3.依赖对象在使用前一定会被完全初始化

4.通用性好

如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,
setter注入
方便再类实例之后,重新对该对象进行配置或注入
1.不能注入一个final修饰的属性
2.注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险

补充:final修饰的属性,需要具备下列两个条件之一:

1.初始化赋值

2.构造函数赋值

 5.@Resource:另一种注入关键字

在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如下代码所示:

@Controller
public class UserController3 {
    @Resource
    private UserService us;

    public void sayHi(){
        us.doService();
        System.out.println("hi,userController~");
    }
}

@Resource和@Autowired的区别

  • 出身不同:@Autowired来自于Spring,⽽ @Resource 来⾃于 JDK 的注解;
  • 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。
  • @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。

补充:

@Autowired

根据类型来获取bean,如果同一个类型的bean只有一个,直接注入成功

如果同一个类型的bean有多个,以名称匹配,注入相同名称的bean

如果没有名称相同的,就报错

6.同一类型多个@Bean报错

1.现象

当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:

@Component
public class Users {
 @Bean
 public User user1() {
 User user = new User();
 user.setId(1);
 user.setName("Java");
 return user;
 }
 @Bean
 public User user2() {
 User user = new User();
 user.setId(2);
 user.setName("MySQL");
 return user;
 }
}

在另一个类中获取User对象:

@Controller
public class UserController4 {
 // 注⼊
 @Resource
 private User user;
 public User getUser() {
 return user;
 }
}

报错了,报错原因为:非唯一的Bean对象

 2.报错处理

解决同⼀个类型,多个 bean 的解决⽅案有以下两个:

  • 使⽤ @Resource(name="user1") 定义。
  • 使⽤ @Qualifier 注解定义名称。

使⽤ @Resource(name="xxx")

使⽤ @Qualifier

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

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

相关文章

二叉树展开为链表

给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。 展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 1&…

CVE-2023-1454注入分析复现

简介 JeecgBoot的代码生成器是一种可以帮助开发者快速构建企业级应用的工具&#xff0c;它可以通过一键生成前后端代码&#xff0c;无需写任何代码&#xff0c;让开发者更多关注业务逻辑。 影响版本 Jeecg-Boot<3.5.1 环境搭建 idea 后端源码&#xff1a; https://git…

【Java SpringBoot Starter】开发一个自己的SpringBoot Starter组件,应该怎么写,需要什么配置

【Java SpringBoot Starter】开发一个自己的SpringBoot Starter组件&#xff0c;应该怎么写&#xff0c;需要什么配置 目录 1. 自定义的Starter&#xff0c;需要的Configuration 类 2. .properties文件的配置&#xff0c;或者yml文件的配置内容&#xff0c;注入bean对象中 …

行业报告 | AI 赋能,人形机器人产业提速,把握产业链受益机会(上)

文 | BFT机器人 01 核心观点 核心观点: 人形机器人产业发展仍处于 0-1 阶段&#xff0c;当前行业投资逻辑偏向事件驱动型的主题投资&#xff0c;但可落地服务场景的人形机器人成长空间非常广阔&#xff0c;值得长期关注。本文将围绕以下热点问题作出讨论: D当前节点人形机器人产…

GPT与人类:人工智能是否能够真正复制人类语言?

人类语言是一种复杂的系统&#xff0c;它不仅包含着无数单词和语法规则&#xff0c;更重要的是具有丰富的含义和上下文。这些语言特征涉及到常识、文化、情感和经验等方面&#xff0c;是人类在长期进化和文明发展中所积累起来的丰富知识和经验的体现。然而&#xff0c;人工智能…

百万级sql server数据库优化案例分享

在我们的IT职业生涯中&#xff0c;能有一次百万级的数据库的优化经历是很难得的&#xff0c;如果你遇到了恭喜你&#xff0c;你的职业生涯将会更加完美&#xff0c;如果你遇到并解决了&#xff0c;那么一定足够你炫耀很多年。 这里我将要分享一次完美的百万级数据库优化经历&am…

高效管理,轻松掌控项目进度

通过Zoho Projects以项目化的方式让企业中的一切任务井井有条&#xff0c;无论是个人事务、团队计划&#xff0c;还是跨部门协同。以下是七个步骤来实现高效的任务协作&#xff0c;使企业中的任务井井有条。 1、安排和跟进任务 通过Zoho Projects项目管理工具轻松创建任务&…

一文了解JNPF低代码开发平台

一、关于低代码 JNPF平台在提供无代码&#xff08;可视化建模&#xff09;和低代码&#xff08;高度可扩展的集成工具以支持跨功能团队协同工作&#xff09;开发工具上是独一无二的。支持简单、快速地构建及不断改进Web端应用程序&#xff0c;可为整个应用程序的生命周期提供全…

matplotlib笔记 sviewgui (鼠标拖拽绘制csv的matplotlib图)

1 先看一下效果 2 导入数据方式 2.1 select选择本地数据 import sviewgui.sview as sv sv.buildGUI()然后会跳出前面的那个GUI界面 2.2 在buildGUI的时候传入数据路径 import sviewgui.sview as sv sv.buildGUI(C:/Users/16000/tip.csv)2.3 参数是DataFrame import sview…

【三维重建】【深度学习】NeuS代码Pytorch实现--训练阶段代码解析(上)

【三维重建】【深度学习】NeuS代码Pytorch实现–训练阶段代码解析(上) 论文提出了一种新颖的神经表面重建方法&#xff0c;称为NeuS&#xff0c;用于从2D图像输入以高保真度重建对象和场景。在NeuS中建议将曲面表示为有符号距离函数(SDF)的零级集&#xff0c;并开发一种新的体绘…

使用wxPython和pillow开发拼图小游戏(一)

刚学习python&#xff0c;心血来潮&#xff0c;使用wxPython和pillow开了一个简单的拼图小游戏&#xff0c;大家分享一下 wxPython是Python语言的一套优秀的GUI图形库&#xff0c;在此项目里主要用来开发GUI客户页面&#xff1b;Pillow是一个非常好用的图像处理库&#xff0c;…

在 3ds Max 中对链模型进行摆放姿势处理

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 建模和“摆姿势”3D链可能看起来是一项繁琐的工作&#xff0c;但实际上可以通过使用阵列工具并将链中的链接视为骨骼来轻松完成。在本教程中&#xff0c;我将向您展示如何对链条进行建模&#xff0c;并通过…

FPGA-DFPGL22学习6-led

系列文章之 上章 FPGA-DFPGL22学习5-VERILOG 文章目录 系列文章之 上章前言一、原理图端口对应 二、程序设计三、程序编写四、仿真五、工程下载 前言 和原子哥一起学习FPGA 开发环境&#xff1a;正点原子 ATK-DFPGL22G 开发板 参考书籍&#xff1a; 《ATK-DFPGL22G之FPGA开…

linux定时删除三天前的binlog日志(docker)

docker的mysql的binlog日志目录 # docker inspect bb61c3c5a7e8shell脚本 写先一个删除的shell脚本 auto-del.sh 真正删除之前&#xff0c;先用下面的语句查下是不是要删除的文件&#xff0c;这里是删除三天前的日志 find /var/lib/docker/volumes/xxxx/_data/ -mtime 3 -n…

C++--day2(字符串、引用、函数重载、哑元)

​​​​​​​​​​​​​​​​​​​​​ ​​​​​​​

【多模态】2、NLTK | 自然语言处理工具包简介

文章目录 一、什么是 NLTK 包二、如何使用三、phrase grounding 使用 NLTK 示例 一、什么是 NLTK 包 NLTK 全称是 Natural Language Toolkit&#xff0c;自然语言处理工具包&#xff0c;是 NLP 领域中常用的 python 库 NLTK 的作用&#xff1a; 语料库文本预处理&#xff1a…

dp算法 力扣123 买卖股票的最佳时机 III

本文是Java代码编写 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 一、题目详情 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意&#xf…

基于R语言Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合方法与应用

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

【MySQL】约束(三)

&#x1f697;MySQL学习第三站~ &#x1f6a9;本文已收录至专栏&#xff1a;MySQL通关路 ❤️每章节附章节思维导图&#xff0c;文末附全文思维导图&#xff0c;感谢各位点赞收藏支持~# 一.引入 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 使用约束可…

DuiLib基本流程解析

文章目录 1、DuiLib基本流程 1、DuiLib基本流程 duilib的基本流程如上图&#xff0c;通过解析一个xml文件&#xff0c;将文件中的内容渲染为窗口界面&#xff0c;这个解析过程由WindowImplBase类来完成。 基本框架如下&#xff1a; 首先在公共头文件中加入如下内容&#xff1a…