spring IOC DI -- IOC详解

news2025/2/24 10:36:00

在这里插入图片描述

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 {
    @Bean
    public 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 {
    @Bean
    public UserInfo userInfo() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName("zhangsan");
        userInfo.setPassword("123456");
        return userInfo;
    }
}

再次执行:

定义多个对象

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

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

    @Bean
    public 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.coloradmin.cn/o/1954309.html

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

相关文章

工程人的“恐惧”

说实话,工程人可真是不容易啊!他们得面对一大堆的挑战和难题,有时候,这些事情足以让任何人感到心惊胆战。想象一下,在施工现场,安全可是头等大事。万一出了啥岔子,后果真是不堪设想。所以呢&…

FPGA实现LVDS接口(2)--IDDR原语的介绍及使用(仿真/源码)

目录 1、IDDR是什么? 2、IDDR的使用 2.1、OPPOSITE_EDGE模式 2.2、SAME_EDGE模式 2.3、SAME_EDGE_PIPELINED模式 3、对IDDR的仿真分析 3.1、OPPOSITE_EDGE模式的仿真结果 3.2、SAME_EDGE模式的仿真结果 3.3、SAME_EDGE_PIPELINED模式 4、IDDR在FPGA底层的布局和布线…

Android studio下载与安装(Windows)

一、安装前依赖 需要在安装前先部署上java环境。 二、下载安装 下载主要是从官网上下载,以下提供一个下载途径:我用夸克网盘分享了「android-studio-2022.3.1.15-windows.zip」,链接:https://pan.quark.cn/s/2021fa13e7ac 我提供…

Golang | Leetcode Golang题解之第295题数据流的中位数

题目: 题解: type MedianFinder struct {nums *redblacktree.Treetotal intleft, right iterator }func Constructor() MedianFinder {return MedianFinder{nums: redblacktree.NewWithIntComparator()} }func (mf *MedianFinder) AddNum(…

全国城市每日气温历史数据(1990-2023.12)

中国城市每日气温历史数据1990-2023.12一、数据介绍 数据名称:中国城市每日气温历史数据 数据范围:371个城市 样本数量:4607078条 指标范围:每日平均气温、最高/低气温 数据日期:1990.1-2023.12 二、数据指标 行…

IOS-05 Swift循环控制语句

在 Swift 编程语言中,控制语句用于决定程序的执行流程,使我们能够根据不同的条件和情况来控制代码的执行顺序。下面我们将详细介绍几种常见的控制语句 一、for 循环 let names ["zhangsan","lisi"] for name in names{print(name…

eclipse ui bug

eclipse ui bug界面缺陷,可能项目过多,特别maven项目过多,下载,自动编译,加载更新界面异常 所有窗口死活Restore不回去了 1)尝试创建项目,还原界面,失败 2)关闭所有窗口&…

Windows搭建Nginx代理本地盘的文件 共享本地文件

一、查询自己的内网IP和外网IP的方法,以及判断是否直接连接到公网 内网IP,即局域网IP: 打开cmd窗口, 输入 ipconfig 后回车 外网IP,即公网IP: 打开cmd窗口,输入curl ifconfig.me指令访问ifconfi…

新160个crackme - 014-Splish

运行分析 需要破解Hard Coded和NameSerial PE分析 ASM程序,32位,无壳 静态分析&动态调试 Hard Coded ida发现关键字符串,进入Hard Code函数 LRESULT __stdcall sub_401178(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam) {c…

vue elementui 上传视频 以及上传视频失败重新上传没反应的处理方法

<template><el-drawertitle"上传视频"size"50%":visible.sync"drawer":direction"direction"><div class"content"><div class"upload-box" v-if"!secondStep"><!--on-exce…

谷粒商城实战笔记-72-商品服务-API-属性分组-获取分类属性分组

文章目录 一&#xff0c;后端接口开发Controller层修改接口接口测试 二&#xff0c;前端开发 这一节的内容是开发获取分类属性分组的接口。 一&#xff0c;后端接口开发 Controller层修改接口 修改AttrGroupController接口。 RequestMapping("/list/{catelogId}")p…

Linuxnat网络配置

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

python—pandas基础(3)

文章目录 虚拟变量变换数值变量分段数据分组基于拆分进行筛选分组汇总使用 agg 函数进行汇总引用自定义函数 长宽格式转换长宽型格式的自由互转 多个数据源的合并数据的横向合并concat 命令一维的Series拼接df对象拼接两个df对象拼接&#xff0c;按列进行拼接两个df对象拼接&am…

55事务、批处理、CBLOB

day55 事务 MySQL&#xff1a;每一条语句都属于独立事务,默认自动管理提交的。 如果需要把多条语句当成一个整体&#xff0c;那么就需要把多条语句放在一个事务里面 开启事务&#xff1a;start transaction 提交事务&#xff1a;commit; 回滚事务&#xff1a;rollback 封装事务…

【安装笔记-20240727-Windows-OpenWrt 23.05 docker 安装 wordpress】

安装笔记-系列文章目录 安装笔记-20240727-Windows-OpenWrt 23.05 docker 安装 wordpress 文章目录 安装笔记-系列文章目录安装笔记-20240727-Windows-OpenWrt 23.05 docker 安装 wordpress 前言一、调试环境操作系统&#xff1a;Windows 10 专业版调试环境 二、安装步骤测试版…

基于SpringBoot的商业航班执飞飞机机型信息管理

目录 前言 一、数据库模型的设计与实现 1、表结构设计 2、数据去重和消歧 二、后台应用程序设计 1、实体类设计 2、业务层及控制层设计与实现 3、视图层的实现 三、系统成果展示 1、飞机机型管理列表 2、机型信息编辑 四、总结 前言 在之前的信息中&#xff0c;我们对…

流媒体服务器二:RTMP协议详解 以及 RTMP学习到什么程度算是合格?

一个问题&#xff1f; 在上一节我们使用SRS搭建了RTMP环境&#xff0c;那么在企业开发中&#xff0c;是否使用第三方的RTMP服务器&#xff08;例如上一节的SRS&#xff09;就可以了呢&#xff1f;或者说&#xff1a;作为一个音视频开发人员&#xff0c;就会配置就OK了呢&#…

windows USB 设备驱动开发-创建安装 Winusb.sys 的驱动程序包

要将 WinUSB 用作设备的功能驱动程序&#xff0c;请创建一个驱动程序包。 驱动程序包必须包含以下文件&#xff1a; WinUSB 辅助安装程序 (Winusbcoinstaller.dll)&#xff1b;KMDF 辅助安装程序 (WdfcoinstallerXXX.dll)&#xff1b;一个 .inf 文件&#xff0c;用于将 Winusb…

MYSQL 第三次作业

1、第三次作业 01、SELECT * FROM student; SELECT * FROM score; 02、SELECT * FROM student LIMIT 1, 3; 03、SELECT * FROM student WHERE department IN (计算机系, 英语系); 04、SELECT * FROM student WHERE birth_year > 1998; 05、SELECT department, COUNT(*) as c…

Corel VideoStudio 会声会影2023旗舰版视频软件

使用新版 Corel VideoStudio 会声会影2023是 一次激活永久使用。 享受有趣轻松的视频编辑体验。通过数百种滤镜、效果、标题、过渡和图形 — 包括新增面部追踪贴纸 — 探索拖放创意。运用直观的工具和即时项目模板&#xff0c;几分钟即可创建出色的视频&#xff01;探索有趣简单…