Spring 面试题

一级目录

二级目录

三级目录

2、IOC是什么 ?

IOC就是控制反转

简述:

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

3、AOP是什么 ?

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

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

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

Spring配置文件有参构造

用构造器构造,创建对象,实例化
在这里插入图片描述

DI依赖注入

1.构造器注入(上面三种就是g)
2.通过set方式注入
在这里插入图片描述

Bean作用域(scopes)

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

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

Bean 的自动装配

在这里插入图片描述

使用注解实现自动装配

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

在这里插入图片描述
@Autowired是用反射实现的

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

Bean的加载过程

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

在这里插入图片描述

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

Bean循环依赖

在这里插入图片描述
在这里插入图片描述
Spring通过提前暴露对象的方式解决循环依赖问题

解决方法
在这里插入图片描述
应用三级缓存来解决循环依赖问题

在这里插入图片描述

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

首先整体查看AbstractApplicationContext#refresh源码

1.spring refresh

2. finishBeanFactoryInitialization(beanFactory)

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

3.

在这里插入图片描述

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

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

在这里插入图片描述

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

在这里插入图片描述

6.调用 dogetBean方法

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

先在一级缓存中找 singletonobjects ,此时不会有a对象,返回空
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

8.调用doCreateBean来创建对象

在这里插入图片描述
在这里插入图片描述

9.createBeanInstance来创建实例

在这里插入图片描述
创建对象,在堆里开辟空间
这样a对象就创建好了,但是b属性默认是空
在这里插入图片描述

A完成实例化但是未完成初始化
在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

9.填充Bean的属性

在这里插入图片描述
在这里插入图片描述

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

https://blog.youkuaiyun.com/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属性,会自动调用其配置的销毁方法。

在这里插入图片描述
1.实例化‘
2.初始化
在这里插入图片描述
在这里插入图片描述

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值