Spring常见面试题(源码)

1、Spring获取Bean的流程

1、加载配置,可以是xml配置或者是配置类,Spring提供了统一的抽象接口BeanDefinitionReader,对于不同的配置有不同的实现类,xml配置是使用XmlBeanDefinitionReader,然后将Bean解析成BeanDefinition对象,然后注册到beanDefinitionMap中,key就是bean的id,value就是BeanDefinition对象,如果有别名的话,在map额外保存一个key是别名,value是id,获取Bean的时候会重定向一次

2、Spring的事件传播器会接受相应事件并传播

  • Bean工厂BeanFactory是一个接口,我们使用的是它的一个实现类DefaultListableBeanFactory
 public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
 }
  • BeanDefinition,表示一个Bean的定义,spring通过BeanDefinition来创建对象,
重要的属性:
	benanClass
	scope
	isLazy
	dependsOn
	primary
	:表示一个Bean是主Bean,在Spring中一个类型可以有多个bean对象,在进行依赖注入时,如果根绝类型找到了多个bean,此时会判断这些bean是否存在一个主bean,如果存在,直接将这个bean注入给属性
	initMethodName
	...
  • 里面有一个属性,存放了所有Bean的定义以及这个Bean被封装成的BeanDefinition对象,
  private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

BeanFactotyPostProcessor Bean工厂的后置处理器即获取工厂中的BeanPostProcessor,调用方法处理bean

1.2Spring获取Bean的流程

1、扫描 ----> 创建BeanDefinition对象 ———>放到beanDefinitionMap中

2、验证 遍历beanDefinitionMap,验证类是否能被创建出来(是否是singleton 是否是抽象类,是否是懒加载,是否是FactoryBean接口的实现类 id属性是否合法 等等),将最终的Bean的id存到一个Set集合中(singleton类型的),这个Set集合的名字是SingletonsCurrentlyInCreation 当一个Bean的生命周期全部结束后,会将这个id移除掉,

3、得到Bean的class对象,根据注入模型,如果设置了构造模式就推断构造方法,判断要使用哪个构造方法进行创建对象,没有设置构造模式默认使用的就是无参的构造方法

4、得到构造器对象,使用反射实例化对象

5、合并BeanDefinition,主要是合并有父类的bean

6、提前暴露一个bean工厂对象---->为了解决循环依赖

7、填充属性,对属性的注入

8、执行部分aware接口,比如ApplicationContextAware接口,为其注入ApplicationContext工厂,等 并执行实现BeanPostProcessor接口中重新的postProcessBeforeInitialization()方法

9、执行剩下的aware接口,并执行Bean的初始化方法,即@PostConstruct标注的方法

10、执行接口版和自定义xml配置版的初始化方法(即实现了InitializingBean接口重写的方法afterPropertiesSet())

11、执行实现的BeanPostProcessor接口的postProcessAfterInitialization()方法,aop代理就是在此方法中完成的

12、将Bean放到单例池中(一级缓存)

13、获取工厂后调用getBean(“id”)调用的就是BeanFactory的doGetBean()方法

1.3Spring的缓存

一级缓存

单例的Bean被创建后就被存放在一级缓存中,其实就是一个Map,只要这个单例bean被创建后,以后再次获取直接从Map中获取

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>

三级缓存

  • singletonFactories,三级缓存,主要存放半成品单例bean的被包装成的ObjectFactory,后续可以解决循环依赖,

    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>
    

二级缓存

  • earlySingletonObjects,二级缓存,从二级缓存中取的半成品的bean,主要存放半成品的bean 如果不存在循环依赖那么创建的bean不会放在三级缓存 Map集合
private final Map<String, Object> earlySingletonObjects = new HashMap<>();

1.4为什么需要三级缓存?

核心就是为了实现AOP,如果注入的早期对象需要的是其代理对象,就需要使用三级缓存为早期对象生成代理,存到二级缓存中去,最终返回早期实例是二级缓存中的其代理对象,使用三级缓存的本质在于解决AOP代理问题

第三级缓存存的是原生早期对象,第二级缓存中存的是经过代理之后的早期对象

2、Spring如何解决循环依赖

2.1什么是循环依赖

就是不同类之间循环引用,比如A类的构造方法依赖B,B类的构造方法依赖A

2.2Spring中的三种循环依赖

1、原型循环依赖(无法解决 只能抛出异常)

每次getBean都是创建新的对象,Spring不会去缓存对象,没有缓存池

2、单例构造方法循环依赖(无法解决,只能抛出异常)

3、单例setter方法循环依赖 (可以解决,提前暴露对象(已完成实例化未完成初始化))

2.3如何判断产生了循环依赖

2.3.1原型模式如何判断产生了循环依赖

原型模式是当getBean(“id”)时Spring才会去根据BeanDefinition定义去反射创建对象,在创建对象时会将当前的beanName存到ThreadLocal中的一个Set集合中,当进行属性注入时发现依赖B,这时就会去获取B的对象,将B的beanName也存进ThreadLocal的Set中,然后B中也依赖A,这时就会去获取A,发现A的beanName已经存在于Set集合中,说明A 和B都处于正在创建的过程中,就可以说明发生了循环依赖,直接抛出异常

2.3.2singleton模式下如何判断产生了循环依赖

当根据A的BeanDefinition去创建对象时,在创建过程中会将beanName存到一个Set集合中,当进行属性注入时发现依赖B,这时就根据B的BeanDefinition创建B,这时B的beanName也会存进Set集合中,创建B的过程发现B依赖A,然后试图将A的beanName存到Set集合中,这时返现Set集合中已经有了A的beanName,即表示A正在创建中,就判断出了发生了循环依赖

2.4Sping如何解决singleton循环依赖

singleton的Bean假设A在创建时会先将这个尚未经过属性注入和初始化的对象包装到一个ObjectFactory对象内,然后存到三级缓存中,key就是beanName,value就是ObjectFactory对象,然后在往下进行属性注入时发现依赖B,就去getBean()去获取B,单例池中没有B,就去根据B的BeanDefinition进而去创建B,在创建B的过程发现B依赖A,就去获取A,就去获取A暴露ObjectFactory对象,通过调用get方法获取A的早期对象,进而完成对A的注入,然后B完成创建后,就将B的对象存到一级缓存中,然后回到A的逻辑完成B的注入

3、BeanFactory与FactoryBean的不同

  • 1、BeanFactory和FactoryBean都是接口
  • 2、BeanFactory就是Spring的Bean工厂,创建并保存了我们的Bean对象,
  • 3、而FactoryBean是Spring提供的专门创建那些复杂对象的,复杂对象即不能直接使用new关键字创建的对象,比如说Connection对象,SqlSessionFactory对象,我们需要实现FactoryBean接口,主要是重写getObject()方法,写创建对象的代码,然后将这个实现类配置在配置文件或者使用配置类的形式,我们获取工厂后使用getBean(“id”)的方式获取的就是这个实现类为我们创建的复杂对象,如果想要获取这个实现类对象,在getBean()获取Bean时id前加入&即可

4、BeanFactory与ApplicationContext的不同

1、ApplicationContext是BeanFactory的子接口

2、 BeanFactory是工厂接口,负责创建Bean的实例,并保存这些单实例的bean在Map中

3、ApplicatonContext是容器的接口,比BeanFactory功能更加强大,更多的负责容器功能的实现,可以基于BeanFactory创建好的对象之上完成强大的容器,AOP DI都是ApplicatonContext接口下的这些类里,

BeanFactory是最底层的接口,ApplicatonContext是留给我们使用的ioc容器接口。

Spring最大的模式就是工厂模式

  • 10
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring码面试题涉及到对Spring框架的原理和核心组件的理解。以下是一些可能的面试题: 1. 请解释一下Spring框架的IoC容器是什么? 引用中提到,Spring的IoC容器是用来管理和组织对象及其依赖关系的容器。它负责创建、配置和管理应用程序中的对象,并将它们装配在一起。通过IoC容器,我们可以将对象之间的依赖关系委托给容器来处理,而不是在代码中显式地进行依赖关系的管理。 2. 请描述一下Spring Bean的生命周期。 引用中提到,Spring Bean的生命周期包括以下几个阶段: - 实例化:创建Bean的实例。 - 属性填充:将Bean的属性值通过依赖注入的方式填充到Bean中。 - 初始化:调用Bean的初始化方法,可以在配置文件中定义或使用注解标记。 - 销毁:当容器关闭时,调用Bean的销毁方法进行清理工作。 3. 请解释一下Spring中的事件传播器是什么? 引用中提到,Spring的事件传播器是一个组件,它可以接受特定的事件并将其传播给对应的监听器。当某个事件发生时,通过事件传播器,我们可以方便地将事件通知多个监听器,以便它们做出相应的处理。 4. 请解释一下BeanFactory和ApplicationContext的区别是什么? BeanFactory是Spring框架的根接口,它定义了IoC容器的基本功能。它提供了创建、配置和管理Bean的能力。而ApplicationContext是BeanFactory的子接口,扩展了更多的功能,如国际化、事件传播器、资加载等。ApplicationContext是更高级、更全面的容器。 以上是一些可能的面试题,希望能对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SSM框架的学习与应用-Java EE企业级应用开发学习记录-(第六天)初识Spring框架](https://download.csdn.net/download/m0_53659738/88275704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [spring相关的码面试题](https://blog.csdn.net/weixin_56993128/article/details/125944512)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Spring见面试题(码)](https://blog.csdn.net/qq_46312987/article/details/118068743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shstart7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值