Spring面试八股文

自动装配原理

1、当启动SpringBoot应用程序时,会先创建SpringApplication对象,在对象的构造方法中会进行某些参数的初始化工作,最主要时判断当前应用程序类型和初始化器和监听器,在这个过程中会加载整个应用程序中的spring.factories文件,将文件的内容放到缓存对象中,以便后续查找。
2、SpringApplication对象创建完毕后,开始执行run方法,来完成整个启动,启动过程中最主要的有两个方法,第一个叫prepareContext,第二个叫refreshContext,在这两个关键方法中完成了自动配置的核心功能,前面的处理逻辑包括上下文的创建,banner的打印,异常报告期的准备等各个准备工作,方便后续来进行调用。
3、在prepareContext方法中完成了对上下文对象的创建和初始化工作,包括了属性的设置,比如环境对象,在整个过程中有个非常重要的方法,叫load,load主要完成一件事,将当前启动类作为一个beanDefinition注册到registery中,方便后续在进行BeanFactoryPostProcessor调用执行的时候,找到对应的主类,来完成@SpringBootApplication和@EnableAutoConfiguration等注解的解析工作。
4、在refreshContext方法中会进行整个容器的刷新工作,会调用spring的refresh()方法,refresh()方法有13个关键的方法,完成整个spring应用程序的启动,在自动装配过程中,会调用invokeBeanFactoryPostProcessor()方法,此方法主要是对ConfigurationClassPostProcessor类的处理,该类是beanfactorypostprocessor的子类,也是beandefinitionregistrypostprocessor的子类,调用时会先调用beandefinitionregistrypostprocessor的时候会解析处理各种注解,包括@PropertySource、@ComponentScan、@Bean、@Import等注解,最主要的是@Import注解的解析。
5、在解析@Import注解时,会有一个getImports的方法,从主类开始递归解析注解,把所有包含@Import的注解都解析到,然后在processImport方法中对Import的类进行分类。

循环依赖问题如何解决

循环依赖就是两个对象相互依赖,形成了一个环形的调用链路。
Spring使用三级缓存来解决循环依赖,核心就是「把实例化和初始化的步骤分开,然后放入缓存中」,供另一个对象调用。
第一级缓存:保存实例化初始化都完成的对象。
第二级缓存:保存完成实例化但未完成初始化的对象。
第三级缓存:保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象。

大致流程

1、A完成实例化后,去创建一个对象工厂,并放入三级缓存

  • 如果A有被AOP代理,那么通过这个工厂获得的就是A代理后的对象
  • 如果A没被AOP代理,那么通过工厂返回的就是A实例化的对象

2、A进行属性注入时,去创建B

3、B完成实例化后创建一个工厂对象,并放入三级缓存

4、B进行属性注入时,需要A,则从三级缓存中取A工厂代理对象并注入,然后删除三级缓存中的A工厂对象,并将A存入二级缓存

5、B完成属性注入,直到初始化结束后,将B存入一级缓存

6、A从一级缓存中获取且注入B,完成后将A从二级缓存删除,并存入一级缓存,循环依赖结束

Spring Bean生命周期

1、实例化Bean:对于BeanFactory容器,当向容器请求一个尚未初始化的Bean时,或初始化Bean时需要注入一个尚未初始化的依赖,容器会调用createBean进行实例化。对于ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition对象中的信息,实例化所有的Bean;
2、设置对象属性(依赖注入):实例化后的对象被封装在BeanWrapper对象中,紧接着Spring根据BeanDefinition中的信息以及通过BeanWrapper提供的设置属性的接口完成依赖注入;
3、处理Aware接口:Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware注入给Bean:

  • 如果这个bean以及实现了beannameaware接口,会调用它实现的setbeanname()方法,此处传递的是spring配文件中的id值;
  • 如果这个bean已经实现了beanfactoryaware接口,会调用它实现setbeanfactory()方法,传递的是spring工厂本身;
  • 如果这个bean已经实现了applicationcontextaware接口,会调用setapplicationcontext()方法,传入spring上下文;

4、beanpostprocessor:如果想要对bean做一些自定义的处理,可以让bean实现beanpostprocessor接口,那么就会调用postprocessorbeforeinitialization()方法;
5、initializingbean与init-method:如果bean在spring配置文件中配置了init-method属性,则会自动调用其配置的方法;
6、如果这个bean实现了beanpostprocessor接口,将会调用postprocessorafterinitialization()方法;由于这个方法是在bean初始化结束时调用的,因而可以被应用于内存或缓存技术;

此时bean已经被正确创建,之后可以使用这个bean了;

7、disposablebean:当bean不再需要时,会经过清理阶段,如果bean实现了disposablebean接口,会调用其实现的destory()方法;
8、destory-method:最后,如果这个bean在spring配置文件中配置了destory-method,会调用配置的销毁方法。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

汉东哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值