当前位置: 首页 > news >正文

详解Spring IoCDI(二)

目录

承接上文:详解Spring IoC&DI (一)

1.IoC详解

1.1方法注解@Bean

1.2方法注解要配合类注解使用 

1.3定义多个对象

1.4重命名Bean

1.5扫描路径

2.DI详解

2.1DI与IoC的关系

2.2属性注入

2.3构造方法注入

 2.4Setter注入

2.5 三种注入优缺点分析

2.6Autowired存在问题

2.6.1Primary

 2.6.2Qualifier

2.6.3Resource


承接上文:详解Spring IoC&DI (一)

1.IoC详解

1.1方法注解@Bean

类注解是添加到某个类上的  但是存在两个问:

1.使⽤外部包⾥的类, 没办法添加类注解

2.⼀个类, 需要多个对象, 比如多个数据源

这种场景, 我们就需要使⽤⽅法注解@Bean

代码示例:

 public class BeanConfig { @Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}}

当我们写完以上代码 ,尝试获取 bean 对象中的 user 时却发现 ,根本获取不到:

@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象User user =context.getBean(User.class);//使⽤对象System.out.println(user);}
}

执行结果如下: 

1.2方法注解要配合类注解使用 

Spring 框架的设计中 ,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到Spring 容器中

如下代码所示:

 @Componentpublic class BeanConfig { @Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}}

再次执⾏以上代码 ,运⾏结果如下:

1.3定义多个对象

多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源.

@Component
public class BeanConfig {@Beanpublic User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user = new User();user.setName("lisi");user.setAge(28);return user;}}

获取对象:

@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class, args);//从Spring上下⽂中获取对象User user1 = (User) context.getBean("user1");User user2 = (User) context.getBean("user2");//使⽤对象System.out.println(user1);System.out.println(user2);}
}

运行结果:

1.4重命名Bean

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

@Bean(name = {"u1","user1"})public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}

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

 User u1 = (User) context.getBean("u1"); 

name={} 可以省略 ,如下代码所⽰: 

 @Bean({"u1","user1"})public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}

只有⼀个名称时, {}也可以省略, :

 @Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}

1.5扫描路径

使⽤前⾯学习的四个注解声明的bean想要⽣效 ,还需要Spring扫描

通过修改项目工程的目录结构进行测试:

运行结果:

 解释: 没有bean的名称为u1,

使⽤五⼤注解声明的bean ,要想⽣效, 还需要配置扫描路径, Spring扫描到这些注解也就是通过

@ComponentScan来配置扫描路径.

@ComponentScan({"com.example.demo"}) 
@SpringBootApplication
public class TestSpringTwoApplication {public static void main(String[] args) {ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象User user =context.getBean(User.class);//使⽤对象System.out.println(user);}
}

@ComponentScan注解虽然没有显式配置,但是实际已经包含在了启动类声明注解

@SpringBootApplication中了,默认扫描的范围是启动类所在包及其子包

 

2.DI详解

2.1DI与IoC的关系

DI(Dependency Injection,依赖注入)和 IoC(Inversion of Control,控制反转)有着密切的关系。 可以说 DI 是实现 IoC 的一种具体方式。 IoC 是一种设计思想,强调将对象之间的控制权进行反转,不再由对象自己去创建或获取其依赖,而是由外部(如框架)来控制和管理依赖关系的创建和注入。 而 DI 则侧重于具体的将依赖对象注入到目标对象的操作,它是实现 IoC 理念的重要手段之一。通过 DI,依赖对象在合适的时候被准确地注入到需要它们的对象中,从而体现了 IoC 的原则。 简单来说,IoC 是更宏观的概念,DI 是实现 IoC 的具体策略和机制。

关于依赖注⼊, Spring也给我们提供了三种⽅式:

属性注⼊(Field Injection)、构造⽅法注⼊(Constructor Injection)、Setter 注⼊(Setter Injection)

2.2属性注入

 @SpringBootApplicationpublic class SpringIocDemoApplication { public static void main(String[] args) { //获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio //从Spring上下⽂中获取对象UserController userController = (UserController) context.getBean("userCont //使⽤对象userController.sayHi(); 11    }}

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

Service类的实现代码如下: 

 import org.springframework.stereotype.Service; @Servicepublic class UserService {public void sayHi() {System.out.println("Hi,UserService");}}

Controller 类的实现代码如下:

 @Controllerpublic class UserController { //注⼊⽅法1: 属性注⼊@Autowiredprivate UserService userService;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();}}

获取Controller中的sayHi方法: 

 @SpringBootApplicationpublic class SpringIocDemoApplication { public static void main(String[] args) { //获取Spring上下⽂对象ApplicationContext context =  SpringApplication.run(TestSpringTwoApplication.class,args);//从Spring上下⽂中获取对象UserController userController = context.getBean(UserController.class);//使⽤对象userController.sayHi(); }}

 运行结果为:

2.3构造方法注入

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

@Controller
public class UserController2 { //注⼊⽅法2: 构造⽅法private UserService userService; @Autowiredpublic UserController2(UserService userService) {this.userService = userService;} public void sayHi(){System.out.println("hi,UserController2...");userService.sayHi();}}

注意事项:如果类只有⼀个构造⽅法 ,那么@Autowired 注解可以省略;如果类中有多个构造⽅法, 那么需要添加上@Autowired 来明确指定到底使⽤哪个构造⽅法。

 2.4Setter注入

Setter 注⼊和属性的 Setter 方法实现类似 ,只不过在设置 set 方法的时候需要加上@Autowired 解 ,如下代码所示:

 @Controllerpublic class UserController3 { //注⼊⽅法3: Setter⽅法注⼊private UserService userService; @Autowiredpublic void setUserService(UserService userService) {this.userService = userService;} public void sayHi(){System.out.println("hi,UserController3...");userService.sayHi();}}

2.5 三种注入优缺点分析

属性注⼊

  优点: 简洁 ,使⽤⽅便; 

  缺点:只能⽤于 IoC 容器 并且只有在使⽤的时候才会出现 NPE 空指针异常)、 能注入⼀个Final修饰的属性

 构造函数注⼊(Spring 4.X推荐) 

 优点:可以注⼊final修饰的属性、注⼊的对象不会被修改、依赖对象在使⽤前⼀定会被完全初始化 ,因为依赖是在类的构造⽅法中执⾏的 ,⽽构造⽅法是在类加载阶段就会执⾏的⽅法、 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

 缺点: 注入多个对象时, 代码会比较繁琐

  Setter注⼊(Spring 3.X推荐)

 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊

缺点:不能注⼊⼀个Final修饰的属性、注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤ , 就有被修改的风险.

2.6Autowired存在问题

当同⼀类型存在多个bean, 使⽤@Autowired会存在问题

@Componentpublic class BeanConfig { @Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;} @Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}}
 @Controllerpublic class UserController { //注⼊user @Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();System.out.println(user);}}

运行结果: 

报错的原因是 ,⾮唯—的 Bean 对象。

Spring提供了以下几种解决⽅案:

2.6.1Primary

@Primary注解: 当存在多个相同类型的Bean注⼊时 ,加上@Primary注解 来确定默认的实现.

 @Componentpublic class BeanConfig { @Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;} @Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}}

 2.6.2Qualifier

指定当前要注⼊的bean对象。 在@Qualifiervalue属性中 ,指定注⼊的bean 的名称。

 @Qualifier注解不能单独使⽤ ,必须配合@Autowired使用

 @Controllerpublic class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}}

2.6.3Resource

使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。

 @Controllerpublic class UserController { @Resource(name = "user2")private User user; public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}}

@Autowird @Resource的区别

•  @Autowired spring框架提供的注解 ,而@ResourceJDK提供的注解

•  @Autowired 默认是按照类型注⼊ ,⽽@Resource是按照名称注⼊ . 相⽐于 @Autowired  来说, @Resource ⽀持更多的参数设置 ,例如 name 设置 ,根据名称获取 Bean

相关文章:

详解Spring IoCDI(二)

目录 承接上文:详解Spring IoC&DI (一) 1.IoC详解 1.1方法注解Bean 1.2方法注解要配合类注解使用 1.3定义多个对象 1.4重命名Bean 1.5扫描路径 2.DI详解 2.1DI与IoC的关系 2.2属性注入 2.3构造方法注入 2.4Setter注入 2.5 三…...

说明白计算机网络之TCP的流量控制与拥塞控制之慢开始算法与拥塞避免算法

TCP的流量控制 利用滑动窗口实现流量控制 设A向B发送数据,连接建立时候,B告诉A自身的接收窗口大小,A的发送窗口大小不能超过接收方B的窗口大小 流量控制:发送方发送速率不要太快,要让接收方来得及接收。窗口大小的单…...

这款信创FTP软件,可实现安全稳定的文件传输

信创,即信息技术应用创新,2018年以来,受“华为、中兴事件”影响,国家将信创产业纳入国家战略,并提出了“28n”发展体系。“8”具体指金融、石油、电力、电信、交通、航空航天、医院、教育等主要行业。目前企业使用比较…...

代码随想录算法训练营第十天|232.用栈实现队列、225. 用队列实现栈

232.用栈实现队列 题目链接:232. 用栈实现队列 文档讲解:代码随想录 状态:写出来 ,但差强人意 思路: 定义两个容器,可以是Stack,也可以是Deque,stackIn相当于临时容器,用来存放元素&…...

STM32 IIC协议

本文代码使用 HAL 库。 文章目录 前言一、什么是IIC协议二、IIC信号三、IIC协议的通讯时序1. 写操作2. 读操作 四、上拉电阻作用总结 前言 从这篇文章开始为大家介绍一些通信协议,包括 UART,SPI,IIC等。 UART串口通讯协议 SPI通信协议 一、…...

Java生成随机数的几种方式

随机数,在一些特殊场景下,是非常常用的。比如一些测试和验证场景、安全加密、随机抽样等都有随机数的‘身影’。 一、 使用java.util.Random类 java.util.Random类提供了更全面的随机数生成功能,包括随机整数、随机浮点数、随机布尔值等。 p…...

【面试】什么是Java虚拟机

目录 1. 说明2. 关键点 1. 说明 1.Java虚拟机(Java Virtual Machine,简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境。2.JVM是Java平台无关性的关键,它允许Java程序在任何支持JVM的硬件和操作系统上运…...

Go 语言的基本构成、要素与编写规范

Go 语言,作为由 Google 开发的现代编程语言,以其简洁、高效和并发编程能力而著称。在构建高性能分布式系统和现代软件开发中,Go 语言正日益受到欢迎。本篇文章将详细探讨 Go 语言程序结构的各个要素,包括函数定义、注释规范、数据…...

从了解到掌握 Spark 计算框架(二)RDD

文章目录 RDD 概述RDD 组成RDD 的作用RDD 算子分类RDD 的创建1.从外部数据源读取2.从已有的集合或数组创建3.从已有的 RDD 进行转换 RDD 常用算子大全转换算子行动算子 RDD 算子综合练习RDD 依赖关系窄依赖宽依赖宽窄依赖算子区分 RDD 血统信息血统信息的作用血统信息的组成代码…...

香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(三)

整期笔记索引 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(一) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(二) 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(…...

【git】常用命令

删除 删除本地分支&#xff1a; // 删除本地分支 git branch -d localBranchName 删除远程仓库分支 git push origin --delete <branch_name> 验证远程分支是否删除 git fetch -p //会清理已经删除的远端分支的引用 git branch -r //列出所有远端分支&#xff0…...

JavaWeb_MySQL数据库

数据库&#xff1a; MySQL数据模型&#xff1a; MySQL是关系型数据库。 SQL&#xff1a; 简介 分类&#xff1a; 数据库设计-DDL 对数据库操作&#xff1a; 表操作&#xff1a; 小练习&#xff1a; 创建下表 SQL代码&#xff1a; create table tb_user (id int primar…...

中国BI步入增长大周期,腾讯云ChatBI加速AI+BI融合

过去十年&#xff0c;大数据技术的快速发展&#xff0c;让数据消费前进一大步&#xff0c;数据价值得到一定程度的挖掘与释放&#xff0c;真正开启了“用数”的大时代。但数据分析繁杂的技术栈、复杂的处理过程以及程式化的交互方式&#xff0c;让“数据消费”的门槛始终降不下…...

揭秘Python:下划线的特殊用法,你绝对想不到!

在Python编程中&#xff0c;下划线&#xff08;underscore&#xff09;是一个常见而又强大的工具。它不仅仅是一个普通的字符&#xff0c;而是具有特殊含义和用法的符号。今天&#xff0c;我们就来揭开Python下划线的神秘面纱&#xff0c;探索它的各种妙用。 下划线的基本用法…...

深入探索Java世界中的Jackson魔法:玩转JsonNode

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 揭秘Jackson库&#xff1a;JSON处理的瑞士军刀 在Java的世界里&#xff0c;处理JSON数据就像是一场探险。幸运的是&#xff0c;Jackson库就像一把多功能的瑞士军刀&#xff0c;为提供了强大而灵活的工具来解析和操作…...

为什么要使用动态代理IP?

一、什么是动态代理IP&#xff1f; 动态代理IP是指利用代理服务器来转发网络请求&#xff0c;并通过不断更新IP地址来保护访问者的原始IP&#xff0c;从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用&#xff0c;能够帮助用户…...

【PB案例学习笔记】-09滚动条使用

写在前面 这是PB案例学习笔记系列文章的第8篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gitee…...

C++中常见的构造函数类别

目录 摘要 默认构造函数&#xff08;Default Constructor&#xff09;&#xff1a; 带参数的构造函数&#xff08;Parameterized Constructor&#xff09;&#xff1a; 拷贝构造函数&#xff08;Copy Constructor&#xff09;&#xff1a; 移动构造函数&#xff08;Move C…...

万界星空科技MES系统功能介绍

制造执行系统或MES 是一个全面的动态软件系统&#xff0c;用于监视、跟踪、记录和控制从原材料到成品的制造过程。MES在企业资源规划(ERP) 和过程控制系统之间提供了一个功能层&#xff0c;为决策者提供了提高车间效率和优化生产所需的数据。 万界星空科技MES 系统基础功能&am…...

炸裂的开源AI语音生成模型ChatTTS

今天看到GitHub上开源了一个非常厉害的AI语音生成模型ChatTTS&#xff0c;可以生成和人类声音非常接近的语音&#xff0c;而且有语气、语调、可以停顿和发出笑声&#xff0c;再也没有了以前的AI味道 体验地址&#xff1a;https://colab.research.google.com/drive/1MYep5f0-BJ…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...