Spring、SpringMVC、SpringBoot面试题
一、什么是Spring
1、Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。
2、常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置,我在学习的过程中主要是用的注解的配置方式
3、Spring 框架已经集成了20多个模块,常见的模块有 :
Spring Cord(核心容器):核心容器提供Spring框架的基本功能。
Spring Context(应用上下文):是一个配置文件,向Spring框架提供上下文信息。
SpringAop(面向切面编程):是面向对象编程的有效补充和完善,Spring的AOP是基于动态代理来实现的
SpringDao(JDBC和Dao模块):JDBC、DAO的抽象层提供了有意义的层次结构,可以用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。
Spring ORM(对象实体映射):Spring框架插入了若干个ORM框架,从而提供了对象的关系工具,其中包括Hibernate、JDO和IBatis SQL Map等,所有这些都遵从Spring的通用事务和DAO异常层次结构
Spring Web(Web模块):Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。
二、在Spring中有几种配置Bean的方式
1、基于XML的配置
2、基于注解的配置
3、基于java的配置
三、BeanFactory和FactoryBean的区别:
BeanFactory是Spring容器,是Spring中所有工厂的顶级父类,FactoryBean是一个特殊的bean,用于创建bean
四、BeanFactory和ApplicationContext的区别
1、BeanFactory:BeanFactory在启动的时候不会去实例化bean,从容器中拿bean的时候才会去实例化
2、ApplicationContext:ApplicationContext是在启动的时候就把所有的bean全部实例化,他还可以为bean配置lazy-init=true来让bean延迟实例化。
五、Spring框架中单例bean是线程安全的嘛?
1、是线程不安全的,但是Spring中的bean是无状态的,也就是不存储数据,所以某种程度上又是安全的。
2、解决线程安全问题:
a.把bean的作用域改为非单例 prototype
b.将共享变量放到ThreadLocal中,ThreadLocal是线程私有变量,线程间隔离,也可以解决线程安全问题
六、Spring Bean有哪些作用域,他们之间有什么区别
1、singleton:是bean默认的作用范围,单例的即不管有多少个请求,每个容器都只有一个bean实例,此模式有bean factory自身来维护
2、propertype:多例的,即可以为每一个bean提供一个实例
3、request:在请求bean范围内会为每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
4、session:与请求范围类似,确保每一个session中有一个bean实例,在session过期后,bean也会随之消失。
七、用过的重要的Spring注解
@component 定义bean
@controller 用于表现层定义bean
@service 用于业务层定义bean
@repository 用于数据层定义bean
@Bean 定义其他bean对象
@componentScan 用于设定扫描路径,此注解只能添加一次,多个数据可以使用数组格式
@Scope 定义bean的作用范围
@preDestroy 定义bean的生命周期
@Autowired 依赖注入,自动装配
八、简述Spring容器中bean的生命周期
====> 分为六个阶段:BeanDefinition -> 实例化 -> 依赖注入 -> 初始化 -> 放到容器中使用 -> 销毁
1、先通过配置文件或者注解拿到所有的beandefinition,并放到BeanDefinitionMap中
2、从BeanDefinitionMap中拿到bean定义并进行实例化
3、依赖注入,给容器中bean中的属性赋值
4、初始化,给属性赋值
5、初始化完成后,bean真正创建完成,就可以把bean放到Spring中,ConcurrentHashMap,我们使用的时候就可以通过getBean来获取bean
6、容器销毁的时候,bean也跟着销毁。
BeanDefinition是bean定义。描述的是 这个bean的类型,即这个bean的名字、有哪些属性、有哪些构造函数、有哪些方法。
九、IOC(控制反转)
使用对象时,由主动new对象转换为由外部提供对象,对象的创建权由程序转移到外部,这样的思想称之为控制反转思想
十、DI(依赖注入)
在容器中建立bean和bean之间的依赖关系的整个过程,称之为依赖注入
十一、AOP(面向切面编程)
基础概念:面向切面编程,把公共的代码抽取出来,并不改变原有代码功能基础上对方法的功能进行增强。
1、连接点:所有可以被功能增强的方法
2、切入点:进行了功能增强的方法
3、切面:切入点+通知
4、通知:所有的共性功能
5、通知类:通知所在的类
Aop的底层原理:动态代理。在程序运行期间动态的生成一个代理对象,当调用到原始方法时,真正执行的是代理对象的代理方法。
动态代理实现方式有两种,基于JDK的动态代理(反射)和基于CGLib的动态代理(继承)。
十三、 spring中关于循环依赖的问题是如何解决的
- 如果在代码中,把两个bean或者多个bean相互持有对方的引用,就会发生循环依赖问题。循环依赖会导致注入出现死循环。
- 循环依赖有三种以来形态
- 第一种是:互相依赖 例如:A依赖B,B依赖A
- 第二种是:三者间依赖
- 第三种: 自我依赖
- 循环依赖有三种以来形态
- spring设置了三级缓存来解决循环依赖问题
- 当我们通过getBean()获得对象实例的时候,spring会先从一级缓存中寻找实例化bean,如果一级缓存中没有找到,则会在二级缓存中再次寻找这个实例化bean,当还没找到的时候。意味着bean还没有被实例化, 所以spring会初期去实例化这个bean,而初期实例化的bean会加入二级缓存中,我们称之为早期bean,同时加入标记,表示其是否存在循环依赖,如果不存在将其放入二级缓存,如果存在则等待下次轮循的时候去赋值,也就是解析Autowired的时候去赋值,然后将目标bean存入一级缓存中,
-
- 一级缓存:所有成熟的bean
- 二级缓存:原生的早期bean
- 三级缓存:代理的bean
- 三级缓存的作用:在创建bean的时候发现其是需要用到代理工厂来创建bean的,则会将创建好的bean放到三级缓存最终再赋值到一级缓存
十四、 spring中那些循环依赖无法解决
- 多实例bean,通过setter注入
- 构造器注入bean
- 单例的代理bean通过setter注入的情况下
- 设置了dependsOn注解的bean