spring IOC DI -- IOC详解

在这里插入图片描述

T04BF

👋专栏: 算法|JAVA|MySQL|C语言

🫵 今天你敲代码了吗

文章目录

      • 4.2 Ioc 详解
        • 4.2.1 Bean的存储
          • @Controller(控制器存储)
          • @Service (服务存储)
          • @Repository(仓库存储)
          • @Component(组件存储)
          • @Configuration(配置存储)
        • 4.2.2 为什么需要这么多类注解?
        • 4.2.3方法注解@Bean
          • 定义多个对象
          • 重命名Bean
        • 4.3 Sping扫描路径

4.2 Ioc 详解

Ioc控制反转,就是将对象的控制权交给Spring的Ioc容器,由Ioc容器创建并管理对象,也就是Bean的存储

4.2.1 Bean的存储

共有两类注解可以实现:

  1. 类注解:@Controller @Service @Repository @Component @Configuration
  2. 方法注解: @Bean
@Controller(控制器存储)

使用@Controller存储bean

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

从Spring容器中获取对象

@SpringBootApplication
public class Je20240721Application {public static void main(String[] args) {//获取Spring上下文ApplicationContext context = SpringApplication.run(Je20240721Application.class, args);//从Spring上下文中获取对象UserController controller = context.getBean(UserController.class);//使用对象controller.sayHi();}
}
/*
Spring上下文指的就是ApplicationContext,就是表示当前的运行环境,
也可以看成一个容器,容器里面存了很多内容,这些内容是当前运行的环境
*/

运行后查看日志:


但是如果我们将@Controller去掉:



报错信息显示:找不到类型org.jwcb.je20240721.iocExample.UserController的bean

获取bean的其他方式



这里我们是根据类型来查找对象,但是如果同一个类型存在多个Bean,怎么来获取呢??


还可以通过Bean的名称来获取Bean对象

那么Bean的名称是什么呢??

来自官方的定义是:

即Spring为bean生成了唯一的名字,命名约定使用java标准约定最为实例字段名,即以小写字母开头,使用小驼峰式
如UserController -> userController

但是存在特殊情况:当有多个字符并且第一个和第二个都是大写的时候,将保留原来的大小写,也就是bean名和类名一致

@SpringBootApplication
public class Je20240721Application {public static void main(String[] args) {//获取Spring上下文ApplicationContext context = SpringApplication.run(Je20240721Application.class, args);//从Spring上下文中获取对象UserController controller1 = (UserController) context.getBean("userController");UserController controller2 = context.getBean(UserController.class);UserController controller3 = context.getBean(UserController.class, "userController");System.out.println(controller1);System.out.println(controller2);System.out.println(controller3);}
}

查看日志:


地址一样,说明是同一个对象,即Spring框架默认使用的是单例模式来管理Bean

Spring框架默认使用单例模式来管理Bean的优势??

  1. 资源利用:减少了对象的创建和销毁,特别是在那些创建实例需要消耗大量资源的情况(如连接数据库等)
  2. 状态共享:应用于需要共享状态(如配置信息,缓存数据等)的场景
  3. 易于测试:可以轻松地替换或模拟Bean
  4. 简化编程模型:开发者不必再担心对象的创建和销毁,也不需要考虑对象之间的依赖关系
  5. 一致性:对于分布式系统来说,单例模式有利于保证应用行为的一致性

但是,值得注意的是,单例模式也有局限性.在多线程环境下,不正确使用单例模式可能会出现线程安全问题
ApplicationContext 提供的获取

bean的方式,是父类BeanFactory提供的功能,那么这两者的区别在哪?

  1. 从继承与功能方面来说,BeanFactory提供了基础的访问容器的能力,而ApplicationContext 除了继承BeanFactory的所有功能之外,还提供了国际化支持,资源访问支持,以及事件传播方面的支持

(1)国际化支持:使得应用可以个人根据不同的语言环境展示相应的内容.这主要通过 MessageSource
接口实现,该接口允许应用访问不同语言的消息属性文件(如 properties 文件)。通过配MessageSource
bean,并指定资源文件的基础名称(basename),ApplicationContext
可以在运行时根据当前的语言环境(Locale)来查找和返回相应的消息。国际化支持在开发多语言应用时非常有用,例如,一个网站可能需要根据用户的语言偏好显示不同的内容。通过配置和使用
ApplicationContext 的国际化支持,可以轻松地实现这一需求。

(2)资源访问支持:ApplicationContext 实现了 ResourceLoader
接口,提供了资源访问的能力。这意味着应用可以通过 ApplicationContext 访问各种资源,如文件、URL 等。通过使用
getResource() 方法,应用可以获取到资源的 Resource
表示,进而进行读取、写入等操作。资源访问支持使得应用能够灵活地访问和管理各种资源。例如,应用可能需要读取配置文件、模板文件或图片等资源,通过
ApplicationContext 提供的资源访问支持,可以方便地实现这些需求。

(3)事件传播支持:ApplicationContext
提供了事件传播的能力,允许应用中的组件在特定事件发生时进行通信和响应。这主要通过 ApplicationEvent 类和
ApplicationListener
接口实现。当一个组件发布一个事件时,所有注册了该事件监听的组件都会收到通知,并执行相应的处理逻辑。事件传播支持在需要实现松耦合组件间通信的应用中非常有用。例如,当一个业务操作完成后,可能需要通知其他组件进行相应的处理(如更新缓存、发送通知等)。通过事件传播机制,可以轻松地实现这一需求,而无需在组件间建立直接的依赖关系。

  1. 从性能方面来看,ApplicationContext 是一次性加载并初始化所有的Bean对象,而BeanFactory是需要那个才去加载,因此更加轻量

@Service (服务存储)
@Service
public class UserService {public void sayHello() {System.out.println("hello,UserService");}
}

@Repository(仓库存储)
@Repository
public class UserRepository {public void sayHello() {System.out.println("hello,Repository");}
}

@Component(组件存储)
@Component
public class UserComponent {public void sayHello() {System.out.println("hello,Component");}
}

@Configuration(配置存储)
@Configuration
public class UserConfiguration {public void sayHello() {System.out.println("Hello Configuration");}
}

4.2.2 为什么需要这么多类注解?

实际上是和应用分层是相呼应的,让开发者看到类注解之后,就能了解当前类的用途

  • @Controller:控制层
  • @Service:业务逻辑层
  • @Repository:数据访问层
  • @Configuration:配置层

类注解之间的关系:

可以看到,除了@Component是一个元注解,也就是可以注解其他类注解

4.2.3方法注解@Bean

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

  1. 使用外部包里面的类,没办法添加注解
  2. 一个类,需要多个对象.比如多个数据源

这种场景,就需要使用方法注解@Bean

public class BeanConfig {@Beanpublic UserInfo userInfo() {UserInfo userInfo = new UserInfo();userInfo.setUserName("zhangsan");userInfo.setPassword("123456");return userInfo;}
}

但是当我们尝试去获取对象的时候:

@SpringBootApplication
public class Je20240721Application {public static void main(String[] args) {//获取Spring上下文ApplicationContext context = SpringApplication.run(Je20240721Application.class, args);//从Spring上下文中获取对象UserInfo userInfo = context.getBean(UserInfo.class);System.out.println(userInfo);}
}


实际上,方法注解@Bean是需要搭配5大类注解才能将对象正常的存储到Spring容器里面,5大类注解标记的类使得Spring能够识别并且管理其中的@Bean方法

@Component
public class BeanConfig {@Beanpublic UserInfo userInfo() {UserInfo userInfo = new UserInfo();userInfo.setUserName("zhangsan");userInfo.setPassword("123456");return userInfo;}
}

再次执行:

定义多个对象

在多个数据源的创场景,类是同一个,但是配置不一样,指向不同的数据源,就需要多个对象

@Component
public class BeanConfig {@Beanpublic UserInfo userInfo1() {UserInfo u = new UserInfo();u.setUserName("zhangsan");u.setPassword("123456");return u;}@Beanpublic UserInfo userInfo2() {UserInfo u = new UserInfo();u.setUserName("lisi");u.setPassword("123456");return u;}
}

那么我们如果直接根据类型获取对象:

即期望只有一个匹配,结果发现了两个 userInfo1,userInfo2

从报错信息也可以看出来,实际上**@Bean**注解的bean的名称就是方法名本身

因此可以根据名称获取对象

@SpringBootApplication
public class Je20240721Application {public static void main(String[] args) {//获取Spring上下文ApplicationContext context = SpringApplication.run(Je20240721Application.class, args);//从Spring上下文中获取对象UserInfo userInfo1 = (UserInfo) context.getBean("userInfo1");System.out.println(userInfo1);UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");System.out.println(userInfo2);}
}


重命名Bean

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

@Bean(name = {"u1","u2"})
public UserInfo userInfo1() {UserInfo u = new UserInfo();u.setUserName("zhangsan");u.setPassword("123456");return u;
}


4.3 Sping扫描路径

前面使用的注解声明的bean,一定会生效吗?
尝试改变一下:

再次运行代码:

实际上Spring默认的扫描路径是:

我们可以通过@ComponentScan来配置扫描路径

但是这种做法不推荐使用

感谢您的访问!!期待您的关注!!!

在这里插入图片描述

T04BF

🫵 今天记得敲代码

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

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

相关文章

追问试面试系列:线程池

hi 欢迎来到线程池系列,线程池在面试中出现的频率非常高。 先看面试题 关于线程池的追问试一共整理22问: ● 面试官:为什么要用线程池 ● 面试官:那怎么创建线程池? ● 面试官:为什么不推荐使用Executors类创建线程池? ● 面试官:ThreadPoolExecutor 有哪些常用的方…

Vue如何让用户通过a链接点击下载一个excel文档

在Vue中&#xff0c;通过<a>标签让用户点击下载Excel文档&#xff0c;通常需要确保服务器支持直接下载该文件&#xff0c;并且你有一个可以直接访问该文件的URL。以下是一些步骤和示例&#xff0c;展示如何在Vue应用中实现这一功能。 1. 服务器端支持 首先&#xff0c;…

AI学习指南机器学习篇- 标签传播算法的数学基础

AI学习指南机器学习篇- 标签传播算法的数学基础 引言 标签传播算法是一种常用的无监督学习算法&#xff0c;广泛应用于社区检测、聚类分析、图像分割等领域。本文将介绍标签传播算法背后的数学理论&#xff0c;包括图论、概率图模型等&#xff0c;同时探讨算法的收敛性和稳定…

面试重点---快速排序

快排单趟 快速排序是我们面试中的重点&#xff0c;这个知识点也很抽象&#xff0c;需要我们很好的掌握&#xff0c;而且快速排序的代码也是非常重要&#xff0c;需要我们懂了还不行&#xff0c;必须要手撕代码&#xff0c;学的透彻。 在研究快速排序之前&#xff0c;我们首先…

depcheck 前端依赖检查

介绍 depcheck 是一款用于检测项目中 未使用依赖项 的工具。 depcheck 通过扫描项目文件&#xff0c;帮助你找出未被引用的依赖&#xff0c;从而优化项目。 优势&#xff1a; 简单易用: 仅需几个简单的命令&#xff0c;就能够扫描并列出未使用的依赖项&#xff0c;让你快速了…

GeneCompass:跨物种大模型用于破解基因调控机理

GeneCompass是第一个基于知识的跨物种基础模型&#xff0c;该模型预先训练了来自人类和小鼠的超过1.2亿个单细胞转录组。在预训练过程中&#xff0c;GeneCompass有效整合了四种生物先验知识&#xff0c;以自监督的方式增强了对基因调控机制的理解。对多个下游任务进行微调&…

PlatformIO+ESP32S3学习:通过WIFI与和风天气API获取指定地点的天气情况并显示

1. 硬件准备 你只需要有一个ESP32S3开发板。我目前使用的是&#xff1a; 购买地址&#xff1a;立创ESP32S3R8N8 开发板 2. 和风天气API 2.1. 和风天气介绍 和⻛天气是中国领先的气象科技服务商、国家高新技术 企业&#xff0c;致力于运用先进气象模型结合大数据、人工智能 技术…

成为git砖家(2): gitk 介绍

大家好&#xff0c;我是白鱼。这篇我们介绍 gitk。 gitk 和 fork 界面对比 当我们在 macOS 上执行 brew install git 后&#xff0c; 得到了 git 命令行工具。 然而这条命令并不会安装 gitk. gitk 是 git 自带的图形化界面工具&#xff0c;也可以称为“穷人版 fork”&#xf…

美国演员工会和电视广播艺人工会针对电子游戏发行商的罢工于 7 月 26 日举行

美国演员工会&#xff08;SAG-AFTRA&#xff09;正在对电子游戏发行商进行罢工&#xff0c;以保护演员不被人工智能所利用。经过一年半的谈判&#xff0c;双方仍未达成协议。该工会希望确保人工智能不会被用作利用大型游戏中演员的手段。 他们在网站上声明&#xff0c;“从事电…

JavaScript实战 - 用Canvas画一个心形

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有疑问或建议&#xff0c;请私信或评论留言&#xff01; 前言&#xff1a; 如…

搭建自己的金融数据源和量化分析平台(三):读取深交所股票列表

深交所的股票信息读取比较简单&#xff1a; 看上图&#xff0c;爬虫读取到下载按钮的链接之后发起请求&#xff0c;得到XLS文件后直接解析就可以了。 这里放出深交所爬虫模块的代码&#xff1a; # -*- coding: utf-8 -*- # 深圳交易所爬虫 import osimport pandas as pd imp…

Linux 命令提示符 PS1设置

在 Linux 中&#xff0c;命令行提示符&#xff08;prompt&#xff09;中的 $ 和 # 是 shell 提供的默认字符&#xff0c;用于区分普通用户和超级用户&#xff08;root&#xff09;。$ 通常用于普通用户会话&#xff0c;而 # 用于超级用户会话。这些字符是提示符的一部分&#x…

fastapi教程(四):做出响应

请求体现的是后端的数据服务能力&#xff0c;而响应体现的是后端向前端的数据展示能力。 一&#xff0c;一个完整的web响应应该包含哪些东西 一个完整的 Web 响应通常包含以下几个主要部分&#xff1a; 1. 状态行- HTTP 版本- 状态码- 状态消息例如&#xff1a;HTTP/1.1 200…

AST反混淆进阶系列|各类简单函数调用还原及对应还原插件参考

关注它&#xff0c;不迷路。 本文章中所有内容仅供学习交流&#xff0c;不可用于任何商业用途和非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请联系作者立即删除&#xff01;

全开源收银系统源码-支付通道

1.收银系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网站: HTML5vue2.0element-uicssjs线下收银台&#xff08;安卓/PC收银、安卓自助收银&#xff09;: Dart3框架&#xff1a;Flutter 3.19.6助手: uniapp商城: uniapp 2.支付通道 智慧新零售收银系统…

一下午连续故障两次,谁把我们接口堵死了?!

唉。。。 大家好&#xff0c;我是程序员鱼皮。又来跟着鱼皮学习线上事故的处理经验了喔&#xff01; 事故现场 周一下午&#xff0c;我们的 编程导航网站 连续出现了两次故障&#xff0c;每次持续半小时左右&#xff0c;现象是用户无法正常加载网站&#xff0c;一直转圈圈。 …

Vue3响应式高阶用法之`shallowReadonly()`

Vue3响应式高阶用法之shallowReadonly() 在现代前端开发中&#xff0c;Vue3 提供了丰富的响应式 API 来帮助开发者更高效地管理状态和数据。其中&#xff0c;shallowReadonly() 是一个非常有用的工具&#xff0c;适用于需要部分只读状态的场景。本文将详细介绍 shallowReadonl…

小白学习webgis的详细路线

推荐打开boss直聘搜索相关岗位&#xff0c;查看岗位要求&#xff0c;对症下药是最快的。 第一阶段&#xff1a;基础知识准备 计算机基础 操作系统&#xff1a;理解Windows、Linux或macOS等操作系统的基本操作&#xff0c;学会使用命令行界面。网络基础&#xff1a;掌握TCP/I…

triu三角矩阵案例演示

def subsequent_mask(size):"""生成向后遮掩的掩码张量, 参数size是掩码张量最后两个维度的大小, 它的最后两维形成一个方阵"""# 在函数中, 首先定义掩码张量的形状attn_shape (1, size, size)# 然后使用np.ones方法向这个形状中添加1元素,形成…

平价不入耳运动耳机哪款最好?五款回购榜优品种草

许多有健身运动习惯的朋友在选择耳机时会优先考虑不入耳耳机&#xff0c;因为它佩戴舒适&#xff0c;稳固性和安全性更高&#xff0c;不仅在运动时不会轻易掉落&#xff0c;还能够方便我们在进行户外运动时接收外界的声音。那么&#xff0c;平价不入耳运动耳机哪款最好&#xf…