JAVA面试之spring篇
bigegpt 2025-04-28 23:31 33 浏览
(搜索总结)该篇总结的不多,还会继续添加!
Spring
什么是三级缓存
Spring 使用三级缓存来解决循环依赖问题。三级缓存分别是:
一级缓存(Singleton Objects)
1、存储已经完全初始化完成的单例 Bean。
2、数据结构:Map<String, Object>,键是 Bean 的名称,值是对应的 Bean 实例。
3、作用:当一个 Bean 已经完全初始化后,它会被放入一级缓存,供后续使用。
二级缓存(Early Singleton Objects)
1、存储提前暴露的、尚未完全初始化的 Bean 实例(即“早期引用”)。
2、数据结构:Map<String, Object>,键是 Bean 的名称,值是 Bean 的早期引用。
3、作用:在 Bean 初始化过程中,如果其他 Bean 需要依赖当前 Bean,Spring 会将当前 Bean 的“早期引用”放入二级缓存,以供其他 Bean 使用。
三级缓存(Singleton Factories)
1、存储用于创建早期引用的工厂对象(ObjectFactory)。
2、数据结构:Map<String, ObjectFactory<?>>,键是 Bean 的名称,值是一个工厂对象。
3、作用:当一个 Bean 尚未完全初始化,但需要被其他 Bean 依赖时,Spring 会通过三级缓存中的工厂对象生成一个“早期引用”,并将其放入二级缓存
Spring如何解决循环依赖问题
Spring使用了三级缓存解决了循环依赖的问题。在populateBean()给属性赋值阶段里面Spring会解析你的属性,并且赋值,当发现,A对象里面依赖了B,此时又会走getBean方法,但这个时候,你去缓存中是可以拿的到的。因为我们在对createBeanInstance对象创建完成以后已经放入了缓存当中,所以创建B的时候发现依赖A,直接就从缓存中去拿,此时B创建完,A也创建完,一共执行了4次。至此Bean的创建完成,最后将创建好的Bean放入单例缓存池中。(非单例的实例作用域是不允许出现循环依赖)
BeanFactory和ApplicationContext的区别
1. BeanFactory是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能。
2. ApplicationContext应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能。如国际化,访问资源,载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,消息发送、响应机制,AOP等。
3. BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化。ApplicationContext在启动的时候就把所有的Bean全部实例化了。它还可以为Bean配置lazy-init=true来让Bean延迟实例化
动态代理的实现方式,AOP的实现方式
1. JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
2. CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
3. 区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。
@Transactional错误使用失效场景
1. @Transactional 在private上:当标记在protected、private、package-visible方法上时,不会产生错误,但也不会表现出为它指定的事务配置。可以认为它作为一个普通的方法参与到一个public方法的事务中。
2. @Transactional 的事务传播方式配置错误。
3. @Transactional 注解属性 rollbackFor 设置错误:Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。
4. 同一个类中方法调用,导致@Transactional失效:由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
5. 异常被 catch 捕获导致@Transactional失效。
6. 数据库引擎不支持事务。
Spring中的事务传播机制
1. REQUIRED(默认,常用):支持使用当前事务,如果当前事务不存在,创建一个新事务。eg:方法B用REQUIRED修饰,方法A调用方法B,如果方法A当前没有事务,方法B就新建一个事务(若还有C则B和C在各自的事务中独立执行),如果方法A有事务,方法B就加入到这个事务中,当成一个事务。
2. SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务。
3. MANDATORY:强制,支持使用当前事务,如果当前事务不存在,则抛出Exception。
4. REQUIRES_NEW(常用):创建一个新事务,如果当前事务存在,把当前事务挂起。eg:方法B用REQUIRES_NEW修饰,方法A调用方法B,不管方法A上有没有事务方法B都新建一个事务,在该事务执行。
5. NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起。
6. NEVER:无事务执行,如果当前有事务则抛出Exception。
7. NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。
Spring中Bean的生命周期
Spring框架中,Bean的生命周期指的是从Bean的创建到销毁的一系列过程。这个过程通常涉及到几个关键的步骤,包括Bean的实例化、属性设置、初始化、使用以及销毁。下面详细介绍Spring中Bean的生命周期的主要阶段和相关的配置方法。
1. Bean的创建
当Spring容器启动时,它会根据配置文件(如XML配置、注解配置等)创建并初始化Bean。
2. Bean的实例化
通过构造器创建:当你在类中定义了构造器,并且Spring的配置文件中使用了<bean>标签或者使用了@Component、@Service、@Repository等注解时,Spring会调用这个类的构造器来创建Bean的实例。
通过静态工厂方法:可以通过配置<bean>标签的class属性指定一个静态工厂方法,该方法返回Bean的实例。
通过实例工厂方法:可以通过配置<bean>标签的factory-bean属性指定一个工厂Bean,然后通过factory-method属性指定一个工厂方法。
3. Bean的属性设置
一旦Bean被实例化,Spring会通过依赖注入(Dependency Injection, DI)来设置Bean的属性。这可以通过构造器注入、Setter方法注入或者字段注入等方式实现。
4. Bean的初始化
在Bean的属性被设置之后,Spring会调用一些特定的方法来进行初始化。这可以通过以下几种方式实现:
实现InitializingBean接口:实现afterPropertiesSet()方法。
使用@PostConstruct注解:在方法上添加@PostConstruct注解,该方法将在依赖注入完成后执行。
自定义初始化方法:可以在XML配置文件中使用init-method属性指定一个初始化方法,或者在类上使用@Bean(initMethod="methodName")指定初始化方法名。
5. Bean的使用
一旦Bean被初始化,它就可以被应用程序中的其他组件使用了。
6. Bean的销毁
当Spring容器关闭时,它会管理Bean的销毁过程。这可以通过以下方式实现:
实现DisposableBean接口:实现destroy()方法。
使用@PreDestroy注解:在方法上添加@PreDestroy注解,该方法将在容器销毁Bean之前执行。
自定义销毁方法:可以在XML配置文件中使用destroy-method属性指定一个销毁方法,或者在类上使用@Bean(destroyMethod="methodName")指定销毁方法名。
如下图可以增深理解
Spring的后置处理器
1. BeanPostProcessor:Bean的后置处理器,主要在bean初始化前后工作。(before和after两个回调中间只处理了init-method)
2. InstantiationAwareBeanPostProcessor:继承于BeanPostProcessor,主要在实例化bean前后工作(TargetSource的AOP创建代理对象就是通过该接口实现)
3. BeanFactoryPostProcessor:Bean工厂的后置处理器,在bean定义(bean definitions)加载完成后,bean尚未初始化前执行。
4. BeanDefinitionRegistryPostProcessor:继承于BeanFactoryPostProcessor。其自定义的方法postProcessBeanDefinitionRegistry会在bean定义(bean definitions)将要加载,bean尚未初始化前真执行,即在BeanFactoryPostProcessor的postProcessBeanFactory方法前被调用。
相关推荐
- 当Frida来“敲”门(frida是什么)
-
0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...
- 服务端性能测试实战3-性能测试脚本开发
-
前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...
- Springboot整合Apache Ftpserver拓展功能及业务讲解(三)
-
今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...
- Linux和Windows下:Python Crypto模块安装方式区别
-
一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...
- Python 3 加密简介(python des加密解密)
-
Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...
- 怎样从零开始编译一个魔兽世界开源服务端Windows
-
第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...
- 附1-Conda部署安装及基本使用(conda安装教程)
-
Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...
- 如何配置全世界最小的 MySQL 服务器
-
配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...
- 如何使用Github Action来自动化编译PolarDB-PG数据库
-
随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...
- 面向NDK开发者的Android 7.0变更(ndk android.mk)
-
订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...
- 信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要
-
问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...
- OpenSSH 安全漏洞,修补操作一手掌握
-
1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...
- Linux:lsof命令详解(linux lsof命令详解)
-
介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...
- 幻隐说固态第一期:固态硬盘接口类别
-
前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...
- 新品轰炸 影驰SSD多款产品登Computex
-
分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...
- 一周热门
- 最近发表
-
- 当Frida来“敲”门(frida是什么)
- 服务端性能测试实战3-性能测试脚本开发
- Springboot整合Apache Ftpserver拓展功能及业务讲解(三)
- Linux和Windows下:Python Crypto模块安装方式区别
- Python 3 加密简介(python des加密解密)
- 怎样从零开始编译一个魔兽世界开源服务端Windows
- 附1-Conda部署安装及基本使用(conda安装教程)
- 如何配置全世界最小的 MySQL 服务器
- 如何使用Github Action来自动化编译PolarDB-PG数据库
- 面向NDK开发者的Android 7.0变更(ndk android.mk)
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)