Spring 面试题

一级目录

二级目录

三级目录

2、IOC是什么 ?

IOC就是控制反转

简述:

我们像我们传统的设计中,我们是直接在对象的内部通过 New 来创建对象,是程序主动去创建依赖对象;而IOC是有专门容器来创建这些对
象,既有IOC容器来控制对象的创建,需要我们做得只需要在Spring的配置文件中配置相应的Bean,以及设置相关的属性,Spring容器就自动帮我们生成类的实例对象

3、AOP是什么 ?

AOP
一般称为面向切面,作为面向对象的一种补充

简述:
其实就是将事务、安全、日志等那些与业务无关的业务逻辑,提取出来封装成
一个切面,然后利用Spring的配置文件注入到目标对象中去

优点:
(1):减少系统中的重复代码
(2):降低了模块间的耦合度
(3):提高了系统的可维护性

Spring配置文件有参构造

用构造器构造,创建对象,实例化
Spring 面试题_第1张图片

DI依赖注入

1.构造器注入(上面三种就是g)
2.通过set方式注入
Spring 面试题_第2张图片

Bean作用域(scopes)

1.单例
在这里插入图片描述
全局共享一个bean,只加载一次,共享一个对象

2.原型模式
每次从容器中get时都会产生一个新的对象
在这里插入图片描述

Bean 的自动装配

Spring 面试题_第3张图片

使用注解实现自动装配

大多数情况下是使用注解进行开发

Spring 面试题_第4张图片
@Autowired是用反射实现的

在这里插入图片描述
Dog是类型 dog是名字
分别对应xml文件中的 class 和id
@Resource可以通过名字或者类型查找bean,如果在Spring容器中两个都找不到,才会报错

Bean的加载过程

解析,读 xml 配置,扫描类文件,从配置或者注解中获取 Bean 的定义信息,注册一些扩展功能。
加载,通过解析完的定义信息获取 Bean 实例。

Spring 面试题_第5张图片

获取 BeanName,对传入的 name 进行解析,转化为可以从 Map 中获取到 BeanDefinition 的 bean name。
合并 Bean 定义,对父类的定义进行合并和覆盖,如果父类还有父类,会进行递归合并,以获取完整的 Bean 定义信息。
实例化,使用构造或者工厂方法创建 Bean 实例。
属性填充,寻找并且注入依赖,依赖的 Bean 还会递归调用 getBean 方法获取。
初始化,调用自定义的初始化方法。
获取最终的 Bean,如果是 FactoryBean 需要调用 getObject 方法,如果需要类型转换调用 TypeConverter 进行转化。

Bean循环依赖

Spring 面试题_第6张图片
Spring 面试题_第7张图片
Spring通过提前暴露对象的方式解决循环依赖问题

解决方法
Spring 面试题_第8张图片
应用三级缓存来解决循环依赖问题

Spring 面试题_第9张图片

Spring容器创建之后,会调用它的refresh方法刷新Spring应用的上下文。

首先整体查看AbstractApplicationContext#refresh源码

1.spring refresh

2. finishBeanFactoryInitialization(beanFactory)

            //初始化所有剩下的非懒加载的单例bean
            finishBeanFactoryInitialization(beanFactory);

3.

在这里插入图片描述

此方法是在 finishBeanFactoryInitialization(beanFactory)方法内部

4.将a,b两个bean对象进行实例化,通过beanname

Spring 面试题_第10张图片

5.用a的beanname用getBean方法来获取bean对象

Spring 面试题_第11张图片

6.调用 dogetBean方法

到容器里包含的三级缓存来获取对象
在这里插入图片描述

先在一级缓存中找 singletonobjects ,此时不会有a对象,返回空
Spring 面试题_第12张图片

7.调用createBean方法来创建a对象

在这里插入图片描述
Spring 面试题_第13张图片

8.调用doCreateBean来创建对象

Spring 面试题_第14张图片
Spring 面试题_第15张图片

9.createBeanInstance来创建实例

Spring 面试题_第16张图片
创建对象,在堆里开辟空间
这样a对象就创建好了,但是b属性默认是空
Spring 面试题_第17张图片

A完成实例化但是未完成初始化
Spring 面试题_第18张图片

Spring 面试题_第19张图片

将lambda表达式和key放入三级缓存
在这里插入图片描述

Spring 面试题_第20张图片

Spring 面试题_第21张图片

9.填充Bean的属性

Spring 面试题_第22张图片
Spring 面试题_第23张图片

为什么用三级缓存而不用二级缓存

https://blog.csdn.net/weixin_49592546/article/details/108050566?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

Spring循环依赖三级缓存是否可以减少为二级缓存?

Bean的生命周期

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(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;

②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。

③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;

(4)BeanPostProcessor:

如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization(Object obj, String s)方法。

(5)InitializingBean 与 init-method:

如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

(6)如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法;由于这个方法是在Bean初始化结束时调用的,所以可以被应用于内存或缓存技术;

以上几个步骤完成后,Bean就已经被正确创建了,之后就可以使用这个Bean了。

(7)DisposableBean:

当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;

(8)destroy-method:

最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

进阶版spring bean的完整生命周期
1我们先在我们需要获取bean对象的方法中调用ApplicationContext容器,将XML文件或者JAVA文件作为参数传到对应的容器中
2启动时,容器会帮我们设置配置文件路径,调用AbstractApplicationContext类refresh()方法,实现的ConfigurableApplicationContext接口中的refresh()方法(refresh()方法,它的作用就是:在创建IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh 之后使用的是新建立起来的IOC 容器。refresh 的作用类似于对IOC 容器的重启,在新建立好的容器中对容器进行初始化,对Bean 定义资源进行载入。)
3在refresh()方法中调用obtainFreshBeanFactory方法进行解析XML和注解,并加载Bean定义,注册到IOC容器中。
4然后调用prepareBeanFactory方法做一些预处理,比如设置类加载器
5之后调用invokeBeanFactoryPostProcessors方法管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以再此时对数据进行修改操作
6在调用registerBeanPostProcessors方法注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中,Spring IoC 容器允许 BeanPostProcessor 在容器初始化 bean 的前后,添加自己的逻辑处理。
7之后会做一些初始化容器的一些工作和注册事件监听器
8接下来就是调用finishBeanFactoryInitialization方法进行bean对象的处理
9首先判断:单例、非懒加载、非抽象,满足这三个条件才会调用getBean(Bean实例化都是通过调用该方法实现的)实例化
10getBean中会调用doGetBean,doGetBean中从缓存中拿实例,没有的话则通过scope类型去创建对应的Bean实例,在创建对象之前如果scope是prototype类型的首先会通过isPrototypeCurrentlyInCreation检验是否存在循环依赖
11有的话调用getSingleton(beanName),经过一系列的方法调用,调到doCreateBean,在此方法中调用createBeanInstance方法进行Bean的实例化,通过获取BeanDefinition对象中的信息,实例化所有的bean。
12 在调用populateBean,完成对对象属性的设置(依赖注入),实例化后的对象被封装在BeanWrapper对象中,紧接着,Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。
13 在通过调用initializebean方法中的invokeAwareMethods方法,检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean:
①如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的就是Spring配置文件中Bean的id值;
②如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,传递的是Spring工厂自身。
③如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文;
14 如果想对Bean进行一些自定义的处理,那么可以让Bean实现了BeanPostProcessor接口,那将会调用postProcessBeforeInitialization()方法。可以在初始化前对bean进行操作
15 如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
16 如果这个Bean实现了BeanPostProcessor接口**,将会调用postProcessAfterInitialization()方法,可以初始化后对bean进行操作
17 接下来就可以使用bean了
18 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法;
19 如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。

Spring 面试题_第24张图片
1.实例化‘
2.初始化
Spring 面试题_第25张图片
Spring 面试题_第26张图片

BeanFactory和FactoryBean的区别

BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
BeanFactory,以Factory结尾,表示它是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,

2、FactoryBean

一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。

ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先
区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似

6、Spring配置方式有几种 ?

3种
基于XML的配置、基于注解的配置、基于Java的配置

7、Spring基于xml注入bean的几种方式 ?

Set方法注入
构造器注入:a.通过index设置参数的位置;b.通过type设置参数类型
静态工厂注入
实例工厂

8、IOC注入方式有几种 ?

3种
构造器注入、setter方法注入、根据注解注入

9、AOP实现的关键是什么 ?

关键:
关键在于代理模式
AOP代理主要分为静态代理和动态代理。

静态代理:
代表:AspectJ
解析:就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强,
他会在编译阶段将AspectJ(切面)织入到Java字节码中

动态代理:
代表:Spring AOP
解析:就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为
方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法

两种代理区别:
区别:生成AOP代理对象的时机不同,相对来说AspectJ性能更好,
但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理

11、BeanFactory和ApplicationContext有什么区别 ?

区别:
(1):都是Spring的两大核心接口,都可以当做Spring的容器
(2):ApplicationContext是BeanFactory的子接口
(3):ApplicationContext提供BeanFactory所具有的功能外,还提供了更完整的框架功能
a: 继承MessageSource,因此支持国际化。
b: 统一的资源文件访问方式
c: 提供在监听器中注册bean的事件
d: 同时加载多个配置文件

12、BeanFactory和ApplicationContext是怎么注入Bean的 ?

BeanFactory:
原理:BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某
个Bean时(调用getBean()),才对该Bean进行加载实例化

ApplicationContext:
原理:在容器启动时,一次性创建了所有的Bean

区别:
(1):相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。
当应用程序配置Bean较多时,程序启动较慢
(2):BeanFactory需要手动注册,而ApplicationContext则是自动注册。

Servlet的生命周期:

实例化——>初始init——>接收请求service——>销毁destroy;

14、Spring支持的几种bean的作用域 ?

5种
singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护
prototype:为每一个bean请求提供一个实例。
request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收
session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
global-session:全局作用域,global-session和Portlet应用相关

Spring 框架中都用到了哪些设计模式 ?

工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例
单例模式:Bean默认为单例模式
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate
观察者模式:定义对象键一种一对多的依赖关系(eg: Spring中listener的实现–ApplicationListener)

你可能感兴趣的:(SPRING)