Spring八股文

重点

描述一下bean的生命周期

简述版

  • 调用构造器 或者是通过工厂的方式创建Bean对象
  • 给bean对象的属性注入值
  • 调用初始化方法,进行初始化, 初始化方法是通过init-method来指定的.
  • 使用
  • IOC容器关闭时, 销毁Bean对象

详细:

Spring八股文_第1张图片
1. 实例化 Bean ,反射的方式生成对象
2. 填充 bena 的属性: populateBean(), 循环依赖的问题 ( 三级缓存 )
3. 调用 aware 接口相关的方法:
invokeAwareMethod( 完成 BeanName 可以获取容器 bean 的名称,
BeanFactory 获取当前 bean factory 这也可以调用容器的服务, BeanClassLoader 对象的属性设置 )
4. 调用 BeanPostProcessor 中的前置处理方法:
使用比较多的有 (ApplicationContextPostProcessor 设 置ApplicationContext Environment,ResourceLoader,EmbeddValueResolver 等对象 )
5. 调用 initmethod 方法:
判断是否实现了 InitializingBean 接口,如果有,调用afterPropertiesSet方法
6、如果在配置文件中定义了 init-method 属性,容器将调用这个自定义的初始化方法。
7. 调用 BeanPostProcessor 的后置处理方法:
spring aop 就是在此处实现的, AbstractAutoProxyCreator 注册Destuction相关的回调接口
8. 获取到完整的对象,可以通过 getBean 的方式来进行对象的获取
9. 销毁流程 ①判断是否实现了 DispoableBean 接口②调用 destroyMethod 方法
如果 bean 实现了 DisposableBean 接口,容器将调用 destroy() 方法
如果在配置文件中定义了 destroy-method 属性,容器将调用这个自定义的销毁方法。
参考: 面试题-Spring Bean的生命周期_springbean生命周期面试-CSDN博客

Spring Bean 的作用域都有哪些?如何控制 Bean 的生命周期?


Singleton(单例)
描述: 默认作用域。Spring容器中只创建一个Bean实例,并在整个容器中共享这个实例。
生命周期: 从容器启动到容器关闭期间,Bean实例始终存在。
Prototype(原型)
描述: 每次请求都会创建一个新的Bean实例。每个实例都有独立的生命周期。
生命周期: 每次获取Bean时,都会创建一个新的实例。Bean的生命周期从创建开始,到被垃圾回收时结束。
Request(请求)
描述: 每个HTTP请求都会创建一个新的Bean实例。Bean的生命周期与HTTP请求相对应。
生命周期: 从每个HTTP请求开始到请求结束,每次请求都会创建一个新的Bean实例。
Session(会话)
描述: 每个HTTP会话创建一个新的Bean实例。Bean的生命周期与HTTP会话相对应。
生命周期: 从每个HTTP会话开始到会话结束,每个会话都有一个独立的Bean实例。
GlobalSession(全局会话)
描述: 在Portlet环境中使用。每个全局会话创建一个新的Bean实例。
生命周期: 适用于Portlet应用中的全局会话,每个全局会话有一个独立的Bean实例。

谈谈Spring IOC的理解,原理与实现

控制反转:理论思想,它把传统的对象创建和依赖的管理放在了容器中,由容器控制对象的生命周期,对象与对象之间的关系由容器来管理,也就是说控制权由程序员转移到了容器上。
DIIOC的实现依赖于DI(Dependency Injection,依赖注入),IOC容器负责创建对象,并管理对象之间的依赖关系,这些类之间的依赖关系配置在配置文件中,容器通过配置文件来动态注入依赖关系
容器 :存储对象,使用 map 结构来存储,在 spring 中一般存在三级缓存, singletonObjeacts 存放完整的 bean对象,整个 bean 的生命周期,从创建到使用到销毁的过程全部都是由容器来管理的 (bean 的生命周期)
1. 一般聊 ioc 容器的时候涉及到容器的创建过程 (beanFactory,DefaultListableBeanFactory), bean 工厂 中设置一些参数(BeanPostProcessor,Aeare 接口的子类 ) 等等属性
2. 加载解析 bean 对象,准备要创建的 bean 对象的定义对象 beanDefinition(xml 或者注解的解析过程 )
3.beanFactoryPostProcessor 的处理,此处是扩展点, PlaceHolderConfigurSupport , ConfigurationClassPostProcessor
4.BeanPostProcessor 的注册功能,方便后续对 bean 对象完成具体的扩展功能
5. 通过反射的方式讲 BeanDefinition 对象实例化成具体的 bean 对象
6.bean 对象的初始化过程 ( 填充属性,调用 aware 子类的方法,调用 BeanPostProcessor 前置处理方法,调用init-mehtod 方法, BeanPostProcessor 的后置处理方法 )
7. 生成完整的 bean 对象,通过 getBean 方法可以直接获取
8. 销毁过程
没看过源码?
具体的细节就不清楚了,但是 spring 中的 bean 都是通过反射的方式生成的,同时其中包含了很多的扩展点( 对占位符的处理 ) ,比如最常用的对 BeanFactory 的扩展,对 bean 的扩展,我们在公司对这方面的 使用是比较多的,除此之外,ioc 中最核心的也就是填充具体 bean 的属性,和生命周期 ( 背一下 )

谈一下spring IOC的底层实现

底层实现:工作原理,过程,数据结构,流程,设计模式,设计思想
你对他的理解和你了解过的实现过程
反射,工厂,设计模式,关键的几个方法
createBeanFactory , getBean ,doGetBean , createBean ,
doCreateBean,createBeanInstance(getDeclaredConstructor(),newinstance),populateBean
1. 先通过 createBeanFactory 创建一个 Bean 工厂 (DefaultListableBeanFactory)
2. 开始循环创建对象,因为容器中的 bean 默认都是单例的,所以优先通过 getBean doGetBean 从容器 中查找,找不到的话,
3. 通过 createBean doCreateBean 方法,以反射的方式创建对象,一般情况下使用的是无参的构造器 (getDeclaredConstructor(),newinstance)
4. 进行对象的属性填充 populateBean
5. 进行其他的初始化操作 (initializingBean)

SpringAOP的底层实现原理

aop概念,应用场景,动态代理

aop概念:

面向切面编程,是一种将非业务代码与业务代码进行分离的一种思想

应用场景:

日志记录(Logging):在方法调用前后记录日志信息,用于跟踪方法执行情况、性能监控或调试。
权限检查(Security/Authorization):在方法执行前验证用户是否有权限执行该操作,比如角色检查或资源访问控制。
事务管理(Transaction Management):自动管理数据库事务的开启、提交或回滚,保证数据的一致性。
异常处理(Exception Handling):集中处理特定类型的异常,比如记录异常信息或执行特定的恢复操作。

动态代理:

AOP底层实现原理是动态代理(JDK动态代理+CGLIB动态代理),就是在不修改原有类对象方法的源代码基础上,通过代理对象实现对原有类对象方法的增强,也就是拓展原有类对象的功能。

bean 的创建过程中有一个步骤可以对 bean 进行扩展实现, aop 本身就是一个扩展功能,所以在
BeanPostProcessor 的后置处理方法中来进行实现
1. 代理对象的创建过程( advice ,切面,切点)
2. 通过 jdk 或者 cglib 的方式来生成代理对象
3. 在执行方法调用的时候,会调用到生成的字节码文件中,直接回找到 DynamicAdvisoredInterceptor类中的 intercept 方法,从此方法开始执行
4. 根据之前定义好的通知来生成拦截器
5. 从拦截器链中依次获取每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪
个,会有一个 CglibMethodInvocation 的对象,找的时候是从 -1 的位置依次开始查找并且执行的。

拓展

Spring是如何解决循环依赖的问题的?

三级缓存,提前暴露对象, aop
:什么是循环依赖问题, A 依赖 B B 依赖 C C 依赖 A
:先说明 bean 得创建过程:实例化,初始化(填充属性)
1. 先创建 A 对象,实例化 A 对象,此时 A 对象中的 b 属性为空
2. 从容器中查找 B 对象,如果找到了,直接赋值不存在循环依赖问题 ( 不通 ) ,找不到直接创建 B 对象
3. 实例化 B 对象,此时 B 对象中的 a 属性为空,填充属性 a
4. 从容器中查找 A 对象,找不到,直接创建
此时,如果仔细琢磨的话,会发现 A 对象,是存在的,只不过此时的 A 对象不是一个完整的状态,只 完成了实例化但是未完成初始化,如果在程序调用过程中,拥有了某个对象的引用,能否在后期给他完 成赋值操作,可以优先把非完整状态的对象优先赋值,等待后续操作来完成赋值,相当于提前暴露了某 个不完整对象的引用,所以解决问题的核心在于实例化和初始化分开操作,这也是解决循环依赖问题的关键,
当所有的对象都完成实例化和初始化操作之后,还要把完整对象放到容器中,此时在容器中存在对象 的几种状态,完成实例化= 但未完成初始化,完整状态,因为都在容器中,所以要使用不同的 map 结构 来进行存储,此时就有了一级缓存和二级缓存,如果一级缓存中有了,那么二级缓存中就不会存在同名 的对象,因为他们的查找顺序是1 2 3 这样的方式来查找的。一级缓存中放的是完整对象,二级缓存中放的是非完整对象,
为什么需要三级缓存?三级缓存的 value 类型是 ObjectFactory ,是一个函数式接口 ,存在的意义是保证在整个容器的运行过程中同名的bean 对象只能有一个。
如果一个对象需要被代理,或者说需要生成代理对象,那么要不要优先生成一个普通对象?要普通对象和代理对象是不能同时出现在容器中的,因此当一个对象需要被代理的时候,就要使用代理 对象覆盖掉之前的普通对象,在实际的调用过程中,是没有办法确定什么时候对象被使用,所以就要求 某个对象被调用的时候,优先判断此对象是否需要被代理,类似于一种回调机制的实现,因此传入 lambda表达式的时候,可以通过 lambda 表达式来执行对象的覆盖过程, getEarlyBeanReference() 因此,所有的bean 对象在创建的时候要优先放到三级缓存中,在后续的使用过程中,如果需要被代理 则返回代理对象,如果不需要被代理,则直接返回普通对象

Spring的事务是如何回滚的?

spring 的事务管理是如何实现的?
总: spring 的事务是由 aop 来实现的,首先要生成具体的代理对象,然后按照 aop 的整套流程来执行具体 的操作逻辑,正常情况下要通过通知来完成核心功能,但是事务不是通过通知实现的,而是通过一个 TransactionInterceptor来实现的,然后调用 invoke 来实现具体的逻辑
分:
1. 先做准备工作,解析各个方法上事务相关的属性,根据具体的属性来判断是否开始新事务
2. 当需要开启的时候,获取数据库连接,关闭自动提交功能,开启事务
3. 执行具体的 sql 逻辑操作
4. 在操作过程中,如果执行失败了,那么会通过 completeTransactionAfterThrowing 看来完成事务
的回滚操作,回滚的具体逻辑是通过 doRollBack 方法来实现的,实现的时候也是要先获取链接对象,通 过连接对象来回滚。
5. 如果执行过程中,没有任何意外情况的发生,那么通过 commitTransactionAfterReturning 来完
成事务的提交操作,提交的具体逻辑是通过 doCommit 方法来实现的,实现的时候也要获取链接,通过 链接对象来提交
6. 当事务执行完毕之后需要清除相关的事务信息 cleanupTransactionInfo
如果想要聊的更加细致的话,需要知道 TransactionInfo TransactionsStatus

谈一下spring事务传播?

传播特性有几种?七种
Required Requireds_new,nested,Support,Not_Support,Never,Mandatory
某一个事务嵌套另外一个事务的时候怎么办?
A 方法调用 B 方法, AB 方法都有事务,并且传播特性不同,那么 A 如果有异常, B 怎么办, B 如果有异常, A怎么办?
:事务的传播特性指的是不同方法的嵌套调用过程中,事务该如何进行处理,是同一个事务还是不同 的事务,当出现异常的时候会回滚还是提交,两个方法之间相互影响,在日常工作中,使用比较多的是 required, Requireds_new
1. 先说事务的不同分类,可以分为三类,支持当前事务,不支持当前事务,嵌套事务
2. 如果外层方法是 required ,内层方法是: required requireds_new,nested
3. 如果外层方法是 requireds_new ,内层方法是: required requireds_new,nested
4. 如果外层方法是 nested ,内层方法是: required requireds_new,nested
核心处理逻辑非常简单:
1. 判断内外方法是否是同一事务:
是:异常统一在外层方法处理
不是:内层方法有可能影响到外层方法,但是外层方法是不会影响内层方法的
(大致可以这么理解,但是有个别情况不同, nested

Bean FactoryFactoryBean有什么区别?

相同点:都是用来创建 bean 对象的
不同点:使用 BeanFactory 创建对象的时候,必须要遵循严格的生命周期流程,太复杂了,如果想要简 单的自定义某个对象的创建,同时创建完成的对象想交给spring来管理,那么就需要实现 FactoryBean 接口了它的方法
isSingleton :是否是单例对象
getObjectType :获取返回对象的类型
getObject :自定义创建对象的过程 (new, 反射 , 动态代理 )

缓存的放置时间和删除时间

三级缓存: CreateBeanInstance 之后: addSingletonFactory
二级缓存:第一次从三级缓存确定对象是代理对象还是不同对象的时候,同时删除三级缓存
getSingleton
一级缓存:生成完整对象之后放到一级缓存,删除二三级缓存: addSingleton

Spring中用到的设计模式

单例模式: bean 默认都是单例的
原型模式:指定作用域为 prototype
工厂模式: BeanFactory
模板模式: postProcessBeanFactory onRefresh initPropertyValue
策略模式: XmlBeanDefinitionReader PropertiesBeanDefinitionReader
观察者模式: listener event multicast
适配器模式: Adapter
装饰者模式: BeanWrapper
责任链模式:使用 aop 的时候会生成一个拦截器
代理模式:动态代理
委托者模式: delegate

你可能感兴趣的:(八股文,spring,java,后端)