Java八股文系列之六(Spring)

前沿

spring是java开发日常使用最多的框架,理解并应用好spring是基础核心能力。第一版略显粗糙,持续更新中。

1.什么是Spring循环依赖。

Spring循环依赖指的是两个或多个Bean之间相互依赖,形成一个环状依赖的情况。简单来说,就是A依赖B,B依赖C,C依赖A,这样就形成了一个循环依赖的环。

Spring循环依赖通常会导致Bean无法正确地被实例化,从而导致应用程序无法正常启动或者出现异常。因此,Spring循环依赖是一种需要尽量避免的情况。

Spring循环依赖的解决方法
为了解决Spring循环依赖问题,我们可以采取以下几种方法:

  • 构造函数注入: 在构造函数注入中,Spring会检查循环依赖,并在发现循环依赖时抛出异常,避免死循环。
  • 使用@Lazy注解: @Lazy注解可以延迟Bean的实例化,从而避免循环依赖的问题。
  • 使用setter方法

Spring是如何解决Bean的循环依赖?
Spring是如何解决的循环依赖: 采用三级缓存解决的 就是三个Map ; 关键: 一定要有一个缓存保存它的早期对象作为死循环的出口

一级缓存singletonObjects存放可以使用的单例。
二级缓存earlySingletonObjects存放的是早期的bean,即半成品,此时还无法使用。
三级缓存singletonFactories是一个对象工厂,用于创建对象并放入二级缓存中。同时,如果对象有Aop代理,则对象工厂返回代理对象。

2.BeanPostProcessor作用和使用场景

BeanPostProcessor的主要作用是允许对新创建的bean实例进行一些处理,或者是对bean的某些属性进行修改。具体来说,它可以用于以下几种情况:

  1. 自定义初始化逻辑:可以在bean初始化之前或之后添加一些自定义逻辑,比如日志记录或性能监控。
  2. 代理对象:可以通过AOP(面向方面编程)技术为bean创建代理对象,在方法调用前后添加切面逻辑。
  3. 依赖注入后处理:在Spring自动注入依赖之后,可以进行进一步的处理,比如检查某些依赖是否已经注入,或者根据注入的依赖进行一些初始化操作。
  4. 属性修改:在bean完全初始化之前,可以修改bean的某些属性,或者设置某些默认值。

代码实现(自定义初始化逻辑)

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class CustomInitializationBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Before Initialization : " + beanName);// 这里可以添加自定义的初始化逻辑if (bean instanceof MyBean) {// 对特定bean的处理((MyBean) bean).customInitBefore();}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("After Initialization : " + beanName);// 这里可以添加自定义的初始化逻辑if (bean instanceof MyBean) {// 对特定bean的处理((MyBean) bean).customInitAfter();}return bean;}
}public class MyBean {private String name;// getter和setter方法public void customInitBefore() {System.out.println("Custom Init Before: " + name);// 在初始化之前的自定义逻辑}public void customInitAfter() {System.out.println("Custom Init After: " + name);// 在初始化之后的自定义逻辑}
}

3.Spring中bean的初始化流程

Spring框架中,bean的创建过程是一个复杂且多步骤的过程,涉及到多个阶段和各种机制。以下是Spring中bean创建过程的详细步骤:

1. Bean Definition Loading

Spring通过配置文件(XML、Java配置类、注解等)加载bean定义(BeanDefinition),这些定义描述了bean的配置信息,包括bean的类名、作用域、依赖关系等。

2. Bean Definition Registry

加载的bean定义会被注册到BeanDefinitionRegistry中。Spring使用不同的BeanDefinitionReader来解析配置并将bean定义注册到BeanFactory中。

3. Bean Instantiation

当Spring容器需要一个bean的实例时,它会通过InstantiationStrategy实例化bean。这时只创建了对象,还没有进行依赖注入。

4. Populate Bean Properties (Dependency Injection)

Spring会通过依赖注入(DI)机制将需要的依赖注入到bean中。可以使用以下几种方式进行注入:

  • 构造器注入
  • Setter方法注入
  • 注解(如@Autowired@Inject@Resource

5. BeanPostProcessor - Before Initialization

在bean初始化之前,Spring会调用所有注册的BeanPostProcessorpostProcessBeforeInitialization方法,对bean进行处理。

6. Bean Initialization

  • 如果bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet方法。
  • 如果在bean定义中指定了init-method,Spring会调用该自定义初始化方法。

7. BeanPostProcessor - After Initialization

在bean初始化之后,Spring会调用所有注册的BeanPostProcessorpostProcessAfterInitialization方法,对bean进行进一步处理。

8. Bean Ready for Use

至此,bean已经完全初始化并可以被应用程序使用。

9. Bean Destruction (For Singleton and Prototype Scopes)

当Spring容器关闭时,会对singleton作用域的bean进行销毁处理。

  • 如果bean实现了DisposableBean接口,Spring会调用其destroy方法。
  • 如果在bean定义中指定了destroy-method,Spring会调用该自定义销毁方法。

4.什么是Spring IOC?

Spring IOC(Inversion of Control)是Spring框架的核心特性之一,翻译为“控制反转”。它是一种设计原则,用于将对象的创建和依赖关系的管理从应用程序代码中分离出来,由Spring容器(也称为IOC容器)负责管理。

核心概念

1. 控制反转(Inversion of Control)

控制反转的基本思想是将对象的控制权从应用程序代码中移交给Spring容器。传统的编程方式中,对象是通过代码直接创建和管理的,而在IOC容器中,对象的创建和依赖关系的注入都是由容器来管理的。

2. 依赖注入(Dependency Injection,DI)

依赖注入是实现控制反转的一种方式。它通过构造函数、Setter方法或字段注入将依赖关系注入到对象中,而不是由对象自己创建或查找依赖。

主要优点

  • 解耦:通过依赖注入,对象之间的耦合度大大降低,使代码更容易维护和测试。
  • 易于测试:由于依赖是注入的,可以轻松地使用Mock对象进行单元测试。
  • 灵活性:可以通过配置文件或注解灵活地配置和管理对象的依赖关系。

5.Spring Bean的生命周期

  • 实例化(Instantiation):Spring容器通过反射机制创建bean的实例。

  • 属性注入(Populating Bean Properties):Spring容器将配置中的属性(例如通过XML配置、注解或Java配置类)注入到bean的相应属性中。

  • 设置BeanName(Setting Bean Name):如果bean实现了BeanNameAware接口,Spring容器会调用setBeanName方法,将该bean在容器中的名称传递给它。

  • 设置Bean工厂(Setting Bean Factory):如果bean实现了BeanFactoryAware接口,Spring容器会调用setBeanFactory方法,将BeanFactory实例传递给它。

  • 设置ApplicationContext(Setting ApplicationContext):如果bean实现了ApplicationContextAware接口,Spring容器会调用setApplicationContext方法,将ApplicationContext实例传递给它。

  • Bean的初始化(Bean Initialization):这一阶段包括两部分:

    • 调用BeanPostProcessorpostProcessBeforeInitialization方法:如果bean实现了BeanPostProcessor接口,Spring容器会在bean初始化之前调用它的postProcessBeforeInitialization方法。
    • 调用自定义的初始化方法:Spring容器会调用bean的初始化方法。如果bean实现了InitializingBean接口,会调用其afterPropertiesSet方法。此外,如果bean在配置中指定了init-method属性,也会调用这个自定义初始化方法。
  • 调用BeanPostProcessorpostProcessAfterInitialization方法:如果bean实现了BeanPostProcessor接口,Spring容器会在bean初始化之后调用它的postProcessAfterInitialization方法。

  • Bean的就绪状态(Bean Ready):此时bean已经完全初始化并且可以使用。

  • Bean的销毁(Bean Destruction):当Spring容器关闭时,会执行bean的销毁过程。这一阶段包括:

    • 调用DisposableBeandestroy方法:如果bean实现了DisposableBean接口,Spring容器会调用它的destroy方法。
    • 调用自定义的销毁方法:如果bean在配置中指定了destroy-method属性,Spring容器会调用这个自定义销毁方法。

6.Spring的事物传播模型?

Spring事务传播(Transaction Propagation)定义了一个事务中方法的执行方式,以及是否应该加入到现有事务中。Spring提供了多种事务传播行为,以满足不同的业务需求。以下是Spring支持的主要事务传播行为:

  • REQUIRED

这是默认的传播行为。如果当前存在一个事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

  • REQUIRES_NEW

每次都会新建一个事务。如果当前存在事务,则挂起该事务,直到新事务完成。

  • SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。

  • NOT_SUPPORTED

总是以非事务方式执行。如果当前存在事务,则挂起该事务,直到该方法执行完成。

  • NEVER

总是以非事务方式执行。如果当前存在事务,则抛出异常。

  • MANDATORY

必须在一个已有事务中运行。如果当前没有事务,则抛出异常。

  • NESTED

如果当前存在事务,则在嵌套事务中执行。如果当前没有事务,则创建一个新的事务。嵌套事务在内部使用保存点(savepoint),这意味着它们可以独立于外部事务进行回滚。

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

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

相关文章

何在 Vue3 中使用 Cytoscape 创建交互式网络图

本文由ScriptEcho平台提供技术支持 项目地址:传送门 Vue.js 中加载 Cytoscape.js 的技术实现 应用场景 Cytoscape.js 是一个用于创建交互式网络的可视化库。在生物信息学、社会网络分析和药物发现等领域中得到了广泛应用。 基本功能 本代码片段演示了如何在 V…

二叉树的这五种遍历方法你们都会了吗?

说在前面 🎈二叉树大家应该都很熟了吧,那二叉树的这五种遍历方式你们都会了吗? 以这一二叉树为例子,我们来看看不同遍历方式返回的结果都是怎样的。 前序遍历 前序遍历的顺序是:首先访问根节点,然后递归地…

linux驱动资源没有及时释放排查

linux驱动资源没有及时释放排查 之前项目过程有遇到一个问题,明明应用已经close fd了,但是再次open设备的时候会出现“device is busy”的情况。刚开始出现这个问题的时候,还以为是应用没有及时的close fd导致的异常,同时排查了内…

Java的JDBC与Druid数据连接池笔记

第一章 JDBC 1.1 JDBC简介 1.1.1 JDBC概念 JDBC就是使用Java语言操作关系型数据库的一套API 全称(Java DataBase Connectivity)Java数据库连接 1.1.2 JDBC本质 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口 各个数据库厂商去实现这套接口,提供数据库…

使用 jQuery 选择器获取页面元素,然后利用 jQuery 对象的 css() 方法设置其 display 样式属性,从而实现显示和隐藏效果。

在页面中显示电影排行榜 当单击“(收起)”链接时,排行榜中后三项的电影名称隐藏而且链接的文本更改为“(展开) ” 当单击“(展开)”的链接时,后三项的电影名称重新显示且链接的文本…

视频剪辑技巧大揭秘:轻松掌握为视频添加梦幻光晕效果的绝妙方法!

在这个视觉盛宴的时代,每一个画面都渴望被赋予独特的魅力与魔法。今天,我要为你揭秘一个神秘的视频剪辑技巧——给视频添加光晕效果,让你的作品瞬间脱颖而出,成为朋友圈的焦点 首先,你可以打开原视频进行查看。此时&am…

QT自定义标题栏窗口其一:实现拖动及可拉伸效果

1、效果 2、核心代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(paren

【字节序】

1. 字节序(Endianness)问题 不同计算机体系结构可能采用不同的字节序来存储多字节数据。字节序有两种主要形式: 大端序(Big-endian):高位字节存储在低地址。 小端序(Little-endian&#xff09…

高速公路声光预警定向广播助力安全出行

近年来,高速重大交通事故屡见不鲜,安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段,创新、智能、高效的压降交通事故的发生概率,优化交通安全管控质量,是近年来交管部门的主要工作,也是…

unity UGUI画线(Image方式)

/// <summary>/// 画线/// 注意&#xff1a;startPoint和endPoint&#xff0c;须和lineTransform在同一路径层级下的位置关系&#xff01;&#xff01;&#xff01;/// </summary>/// <param name"self"></param>/// <param name"li…

Asp.net core Authoriation Middleware实现权限控制的例子

ASP.NET Core Authorization Middleware 是 ASP.NET Core 框架中用于处理授权的中间件组件。它允许开发者在应用程序中实现细粒度的访问控制&#xff0c;确保只有合适的用户才能访问特定的资源或执行特定的操作。 核心概念 策略&#xff08;Policies&#xff09;&#xff1a;策…

解决不能拉取 docker 镜像

# 编辑镜像仓库文件 sudo vi /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com","https://s3d6l2fh.mirror.aliyuncs.com"] }# 重启docker sudo systemctl restart docker参考 https://blog.csdn.net/u01019733…

timescaledb:单机基于postgresql-15安装timescaledb

配置yum sudo yum install https://download.postgresql.org/pub/repos/yum/reporpms/F-$(rpm -E %{fedora})-x86_64/pgdg-fedora-repo-latest.noarch.rpm配置yum源 sudo tee /etc/yum.repos.d/timescale_timescaledb.repo <<EOL [timescale_timescaledb] nametimescal…

将强化学习重新引入 RLHF

我们很高兴在 TRL 中介绍 RLOO (REINFORCE Leave One-Out) 训练器。作为一种替代 PPO 的方法&#xff0c;RLOO 是一种新的在线 RLHF 训练算法&#xff0c;旨在使其更易于访问和实施。特别是&#xff0c; RLOO 需要的 GPU 内存更少&#xff0c;并且达到收敛所需的挂钟时间也更短…

前端Vue实现萤石云播放视频

下载依赖 npm install ezuikit-js --save 完整代码 <template><div class"home"><div id"video-container"></div></div> </template> <script> import EZUIKit from "ezuikit-js";export default…

ICAS英格尔引领企业绿色转型之路:深度解析ISO14064温室气体核查与审定服务

在全球范围内&#xff0c;气候变化正迅速成为影响企业战略决策、运营效率及长期可持续发展的关键因素。ICAS英格尔作为全球领先的认证机构&#xff0c;致力于通过ISO14064温室气体核查与审定服务&#xff0c;帮助企业应对这一挑战&#xff0c;实现绿色转型&#xff0c;提升环境…

前端模糊搜索关键字高亮

效果 代码 <template><view class"flexStart new-box"><view class"company"><!-- 输入框样式 --><view class"spaceBetween companyName" click.stop"isCompany true"><input type"text&quo…

如果已经登录,输入白名单路由想访问白名单页面被重定向其他页面

如果用户已经登录&#xff0c;但尝试访问白名单页面时被重定向到了其他页面&#xff0c;这可能是由于路由守卫的逻辑设置不正确。以下是一些可能的原因和解决方案&#xff1a; 可能的原因&#xff1a; 路由守卫逻辑错误&#xff1a;路由守卫可能错误地将已登录用户重定向到登…

C盘满了怎么清理?一招让你远离C盘空间不足的烦恼

C盘满了怎么清理&#xff1f;一招让你远离C盘空间不足的烦恼&#xff0c;当C盘空间满了时&#xff0c;会给我们来一系列烦恼和潜在问题。比如&#xff1a;系统运行缓慢、程序崩溃或无法安装、启动时间变长、系统不稳定、文件管理困难、游戏卡顿、电脑卡顿、系统故障等问题&…

使用css实现打开抽屉效果(css过渡动画)

方法一&#xff0c;使用高度方式&#xff0c;高度从0到展示进行过渡 HTML代码&#xff1a; <div class"container"><div class"menu">菜单</div><div class"box"></div></div>CSS代码&#xff1a; .box {wi…