一、怎么理解SpringIoc

IOC:Inversion Of Control,即控制反转,是一种设计思想。之前对象又程序员自己new自己创建,现在Spring注入给我们,这样的创建权力被反转了。

所谓控制就是对象的创建、初始化、销毁

  1. 创建对象:原来是 new 一个,现在是由 Spring 容器创建
  2. 初始化对象:原来是对象自己通过构造器或者 setter 方法给依赖的对象赋值,现在是由 Spring 容器自动注入
  3. 销毁对象:原来是直接给对象赋值 null 或做一些销毁操作,现在是 Spring 容器管理生命周期负责销毁对象。

控制反转:“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员“反转”给了框架。

如何设计一个IOC容器:

  1. Bean的生命周期管理:需要设计Bean的创建、初始化、销毁等生命周期管理机制,可以考虑使用工厂模式和单例模式来实现。
  2. 依赖注入:需要实现依赖注入的功能,包括属性注入、构造函数注入、方法注入等,可以考虑使用反射机制和XML配置文件来实现。
  3. Bean的作用域:需要支持多种Bean作用域,比如单例、原型、会话、请求等,可以考虑使用Map来存储不同作用域的Bean实例。
  4. AOP功能的支持:需要支持AOP功能,可以考虑使用动态代理机制和切面编程来实现。
  5. 异常处理:需要考虑异常处理机制,包括Bean创建异常、依赖注入异常等,可以考虑使用try-catch机制来处理异常。
  6. 配置文件加载:需要支持从不同的配置文件中加载Bean的相关信息,可以考虑使用XML、注解或者Java配置类来实现

Spring容器中,存储的主要是Bean对象

二、Spring容器的启动流程

1、第一步创建ApplicationContext的过程

这个容器也叫IOC容器、Spring上下文

ApplicationContext容器:管理Bean对象,通过依赖注入的方式组织Bean之间依赖关系,从而解决业务之间的耦合性

然后通过getBean()方法去获得Bean

2、第二步就是读取配置

xml(ClassPathXmlApplicationContext)、javaconfig(AnnotationConfigApplicationContext )、@Bean、@Configuration

3、第三步是扫描

然后会把配置信息读到BeanDefinition,把扫描的bean变成BeanDefinition,这是一个接口里面就定义了beanClass、scope、lazy-init...通过set方法导入

最终以Map<beanName,beanDefinition类型的对象>形式存储在Spring容器当中

beanDefinition算是Bean的中间状态,封装了一个Bean所需定义信息,后续Bean创建完全由beanDefinition说了算

4、第四步创建Bean

会循环所有的beanDefinition对象,拿到beanName之后通过BeanFactory.getBean(beanName)方法创建Bean

BeanFactory组件:Bean工厂,仅仅用来生产Bean,也是一个接口,用了简单工厂的设计模式

5、检查是否为已经创建的Bean

存储格式:singletonObjects<beanName,Object> 也就是单例池

6、获取不到就创建Bean

实例化:通过beanDefinition的getBeanClass反射调用构造方法完成实例化(推断构造方法)

然后依赖注入变成一个完整的Bean,就是解析​@Autowired,然后返回给getBean()

这里涉及到一个问题:循环依赖

就是A依赖注入B,B依赖注入A,造成循环

具体流程:先通过BeanFactory.getBean(A),然后对A进行实例化,再依赖注入解析B,随后就会去BeanFactory.getBean(B),然后就会去单例池里找,找不到再去newB/实例化B,然后发现B依赖注入里面有个A,又需要去BeanFactory.getBean(A)...最终造成依赖循环。

解决方法:Spring三级缓存

7、初始化 

方法回调:

会把这个Bean放在单例池当中

三、Bean的生命周期 

Spring的启动流程就包含Bean的“生”,另外一篇文章也有提到:

https://blog.csdn.net/2303_80933038/article/details/149421133?fromshare=blogdetail&sharetype=blogdetail&sharerId=149421133&sharerefer=PC&sharesource=2303_80933038&sharefrom=from_linkhttps://blog.csdn.net/2303_80933038/article/details/149421133?fromshare=blogdetail&sharetype=blogdetail&sharerId=149421133&sharerefer=PC&sharesource=2303_80933038&sharefrom=from_link我们来谈谈Bean的“死”

当我们调用容器的.close()方法,所有的Bean都会销毁,销毁的过程中也会调销毁的方法回调,只不过实现的不是InitializingBean接口而是DisposableBean接口

然后调用这个接口下的destory()方法进行销毁

扩展接口:

在初始化过程中,Spring会判断该对象是否实现了BeanNameAware接口、BeanClassLoaderAware接口、BeanFactoryAware接口,如果实现了,就表示当前对象必须实现该接口中所定义的setBeanName()、setBeanClassLoader()、setBeanFactory()方法,那Spring就会调用这些方法并传入相应的参数(Aware回调),这是因为setBeanName(BeanFactory,beanFactory),得到这个参数就可以做很多事了比如getBean()

Aware回调后,Spring会判断该对象中是否存在某个方法被@PostConstruct注解了,如果存在,Spring会调用当前对象的此方法(初始化前)

还有Bean.PostProcessors.beforeXX和Bean.PostProcessors.afterXX。

在bean加载/销毁前后,如果想实现某些逻辑:

1、使用init-method和destroy-method

<bean id="myBean" class="com.example.MyBeanClass" init-method="init" destroy-method="destroy"/>

然后,在你的Bean类中实现这些方法:

public class MyBeanClass {public void init() {// 初始化逻辑 } public void destroy() {// 销毁逻辑 } 
}

2、实现InitializingBean和DisposableBean接口,实现afterPropertiesSet和destroy方法

import org.springframework.beans.factory.DisposableBean;  
import org.springframework.beans.factory.InitializingBean;  
public class MyBeanClass implements InitializingBean, DisposableBean { @Override  public void afterPropertiesSet() throws Exception {// 初始化逻辑}@Overridepublic void destroy() throws Exception {// 销毁逻辑}
}

3、使用@PostConstruct和@PreDestroy注解

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBeanClass {  @PostConstruct public void init() {// 初始化逻辑 }@PreDestroy  public void destroy() { // 销毁逻辑  } 
}

4、使用@Bean注解的initMethod和destroyMethod属性

@Configuration public class AppConfig { 
@Bean(initMethod = "init", destroyMethod = "destroy") public MyBeanClass myBean() { return new MyBeanClass(); } 
}

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

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

相关文章

UDP中的单播,多播,广播

文章目录UDP 简单回顾一、单播&#xff08;Unicast&#xff09;定义特点应用举例二、广播&#xff08;Broadcast&#xff09;定义特点应用三、多播&#xff08;Multicast&#xff09;定义特点应用UDP 单播、广播、多播的对比总结额外说明代码简要示例&#xff08;C&#xff09;…

数据库练习3

一、建立product表&#xff0c;操作方式operate表要求&#xff1a;1.定义触发器实现在产品表(product)中每多一个产品,就在操作表(operate)中记录操作方式和时间以及编号记录。注&#xff1a;操作说明&#xff1a;标记执行delete 、insert、 update2.定义触发器实现在产品表(pr…

pycharm和anaconda安装,并配置python虚拟环境

1、pycharm和anaconda安装 PyCharm与Anaconda超详细安装配置教程_anaconda pycharm安装-CSDN博客https://blog.csdn.net/qq_32892383/article/details/116137730 2、pycharm汉化 PyCharm汉化&#xff1a;简单两步搞定&#xff01;PyCharm怎么设置中文简体&#xff0c;为什么…

EP04:【Python 第一弹】函数编程

一、定义 函数指将一组语句的集合通过一个变量名封装起来&#xff0c;调用这个函数变量名&#xff0c;就可以执行函数。 二、特点 减少重复逻辑代码的编写将程序中的逻辑可以进行扩展维护项目程序的代码更简单 三、创建 def 函数名():逻辑代码1逻辑代码2return 结果 函数名…

linux安装Mysql后添加mysql的用户和密码

在 MySQL 中创建用户并设置密码的完整指南如下&#xff1a; 方法 1&#xff1a;使用 CREATE USER 语句&#xff08;推荐&#xff09; -- 创建新用户并设置密码 CREATE USER newuserlocalhost IDENTIFIED BY your_password;-- 授予权限&#xff08;示例&#xff1a;授予所有数据…

React hooks——memo

一、简介React.memo 是 React 提供的一个高阶组件&#xff08;Higher-Order Component&#xff09;&#xff0c;用于优化函数组件的渲染性能&#xff0c;它通过浅比较&#xff08;shallow compare&#xff09;props 的变化来决定是否重新渲染组件。1.1 基本用法const MyCompone…

leetcode15.三数之和题解:逻辑清晰带你分析

介绍 题源 分析 1.双指针固定一个数 首先明白一点&#xff0c;我们有三个数&#xff0c;我们想使用双指针&#xff0c;那就必须固定一个数。 2.二分 本题还涉及二分&#xff0c;双指针经常和二分结合使用&#xff08;二分本质就是双指针&#xff0c;仔细思考这思考这句话&…

exports使用 package.json字段控制如何访问你的 npm 包

目录 想象一下你正在开发一个 npm 包…… 术语 什么是exports领域&#xff1f; exports好处 保护内部文件 多格式包 将子路径映射到dist目录 子路径导出 单一入口点 多个入口点 公开软件包文件的子集 有条件出口 设置使用条件 默认条件 句法 针对 Node.js 和浏…

AngularJS 安装使用教程

一、AngularJS 简介 AngularJS 是 Google 开发的一款前端 JavaScript 框架&#xff0c;采用 MVVM 架构&#xff0c;提供了数据双向绑定、依赖注入、模块化、路由管理等强大功能&#xff0c;适合构建单页面应用&#xff08;SPA&#xff09;。注意&#xff1a;AngularJS&#xf…

基于python和neo4j构建知识图谱医药问答系统

一、pyahocorasick1.安装 pyahocorasick 包&#xff1a; pip install pyahocorasick -i https://pypi.tuna.tsinghua.edu.cn/simple/pip install pyahocorasick &#xff1a;安装名为 pyahocorasick 的第三方库&#x1f449; 这个库是一个 Aho-Corasick 多模匹配算法 的 Python…

片上网络(NoC)拓扑结构比较

1. 拓扑结构拓扑结构延迟吞吐量跳数功耗面积开销可扩展性容错性布线复杂度适合通信模式Mesh&#xff08;网格&#xff09;低&#xff08;O(√N)&#xff09;高&#xff08;多路径并行&#xff09;O(√N)中高&#xff08;路由器多&#xff09;中高&#xff08;规则布线&#xff…

git merge 命令有什么作用?具体如何使用?

回答重点git merge 命令主要用于将两个分支的历史和内容合并在一起。简而言之&#xff0c;它会将一个分支的更改引入到当前分支中。常见的使用场景是将功能分支&#xff08;feature branch&#xff09;的修改合并回主分支&#xff08;main branch&#xff09;或者开发分支&…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - jieba库分词简介及使用

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解 jieba库分词简介及使用 视频在线地址&…

大模型的后训练与逻辑能力

《DeepSeek原生应用与智能体开发实践》【摘要 书评 试读】- 京东图书 在人工智能与机器学习领域&#xff0c;模型的后训练阶段不仅是技术流程中的关键环节&#xff0c;更是提升模型性能&#xff0c;尤其是数学逻辑能力的“黄金时期”。这一阶段&#xff0c;通过对已初步训练好…

pycharm安装教程-PyCharm2025安装步骤【MAC版】附带安装包

pycharm安装教程-PyCharm2025安装详细步骤【MAC版】安装安装包获取&#xff08;文章末尾&#xff09;今天来给大家分享 Mac 系统安装 PyCharm&#xff0c;附带安装包资源安装&#xff0c; PyCharm 相关就不叙述了&#xff0c;直接开始安装&#xff01; 安装 2024版本、2025年…

【React Native】路由跳转

Link 跳转的路径&#xff0c;就在href里写/details。路径都是相对于app目录来写的&#xff0c;也就是说app目录就是/。很多时候&#xff0c;需要跳转的组件比较复杂。比方说&#xff0c;要在里面要嵌套按钮&#xff0c;或者其他东西。这种情况下&#xff0c;就可以在Link组件里…

使用 Spring Boot + AbstractRoutingDataSource 实现动态切换数据源

1. 动态切换数据源的原理AbstractRoutingDataSource 是 Spring 提供的一个抽象类&#xff0c;它通过实现 determineCurrentLookupKey 方法&#xff0c;根据上下文信息决定当前使用的数据源。核心流程如下&#xff1a;定义多数据源配置&#xff1a;注册多个数据源。实现动态数据…

Kubernetes (K8S)知识详解

Kubernetes (K8S) 是什么&#xff1f; Kubernetes 是 Google 在 2014 年开源的生产级别的容器编排技术&#xff08;编排也可以简单理解为调度、管理&#xff09;&#xff0c;用于容器化应用的自动化部署、扩展和管理。它的前身是 Google 内部的 Borg 项目&#xff0c;Borg 是 …

在github上传python项目,然后在另外一台电脑下载下来后如何保障成功运行

如何在 GitHub 上传并在另一台电脑成功运行 Python 项目✅ 一、上传前&#xff08;本地准备&#xff09; 在你的项目文件夹中进行以下准备&#xff1a; 1. 确保结构清晰 my_project/ ├── main.py ├── utils.py ├── config.yaml ├── requirements.txt └── README…

详解Mysql Order by排序底层原理

MySQL 的 ORDER BY 子句实现排序是一个涉及查询优化、内存管理和磁盘 I/O 的复杂过程。其核心目标是高效地将结果集按照指定列和顺序排列。一、确定排序模式 (Sort Mode)MySQL 根据查询特性和系统变量决定采用哪种排序策略&#xff1a;1.1 Rowid 排序<sort_key, rowid> 模…