Spring框架面试题--由浅入深

简介: 从今天开始我会持续更新面试题,其中涵盖了:Java基础、多线程、IO、高并发、集合框架、数据库、框架以及分布式技术。持续更新中·······

1. 什么是spring?


  • Spring 是个java企业级应用的开源开发框架。Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用。Spring 框架目标是简化Java企业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯。


2. 你们项目中为什么使用Spring框架?


这么问的话,就直接说Spring框架的好处就可以了。比如说Spring有以下特点:

  • 轻量:Spring 是轻量的,基本的版本大约2MB。
  • 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。
  • 面向切面的编程(AOP):Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
  • 容器:Spring 包含并管理应用中对象的生命周期和配置。
  • MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。
  • 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
  • 异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。


3. Autowired和Resource关键字的区别?


@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。

1)、共同点

两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。

2)、不同点

(1)@Autowired

@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;按照byType注入。

public class TestServiceImpl {
 // 下面两种@Autowired只要使用一种即可
 @Autowired
 private UserDao userDao; // 用于字段上
 @Autowired
 public void setUserDao(UserDao userDao) { // 用于属性的方法上
 this.userDao = userDao;
 }
}
复制代码

@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualififier注解一起使用。如下:

public class TestServiceImpl {
 @Autowired
 @Qualifier("userDao")
 private UserDao userDao; }
复制代码

(2)@Resource

@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。

public class TestServiceImpl {
 // 下面两种@Resource只要使用一种即可
 @Resource(name="userDao")
 private UserDao userDao; // 用于字段上
 @Resource(name="userDao")
 public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
 this.userDao = userDao;
 }
}
复制代码

注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。

@Resource装配顺序:

  • 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
  • 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
  • 如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
  • 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。

@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。


4. 依赖注入的方式有几种,各是什么?


  • 构造器注入 : 将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。

优点: 对象初始化完成后便可获得可使用的对象。

缺点: 当需要注入的对象很多时,构造器参数列表将会很长; 不够灵活。若有多种注入方式,每种方式只需注入指定几个依赖,那么就需要提供多个重载的构造函数,麻烦。

  • setter方法注入 : IoC Service Provider通过调用成员变量提供的setter函数将被依赖对象注入给依赖类。

优点: 灵活。可以选择性地注入需要的对象。

缺点: 依赖对象初始化完成后由于尚未注入被依赖对象,因此还不能使用。

  • 接口注入 依赖类必须要实现指定的接口,然后实现该接口中的一个函数,该函数就是用于依赖注入。该函数的参数就是要注入的对象。

优点 接口注入中,接口的名字、函数的名字都不重要,只要保证函数的参数是要注入的对象类型即可。

缺点: 侵入行太强,不建议使用。


5. 讲一下什么是Spring


Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。

主要由以下几个模块组成:

  • Spring Core:核心类库,提供IOC服务;
  • Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
  • Spring AOP:AOP服务;
  • Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;
  • Spring ORM:对现有的ORM框架的支持;
  • Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;
  • Spring MVC:提供面向Web应用的Model-View-Controller实现。


6. 说说你对Spring MVC的理解


什么是MVC模式 :MVC是一种设计模式

  • M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity)
  • V-View 视图(做界面的展示 jsp,html……)
  • C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)

springMVC是一个MVC的开源框架,springMVC=struts2+spring,springMVC就相当于是Struts2加上sring的整合,但是这里有一个疑惑就是,springMVC和spring是什么样的关系呢?这个在百度百科上有一个很好的解释:意思是说,springMVC是spring的一个后续产品,其实就是spring在原有基础上,又提供了web应用的MVC模块,可以简单的把springMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),网络上经常会说springMVC和spring无缝集成,其实springMVC就是spring的一个子模块,所以根本不需要同spring进行整合。

工作原理:

1、 用户发送请求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器

拦截器(如果有则生成)一并返回给DispatcherServlet。

4、 DispatcherServlet调用HandlerAdapter处理器适配器。

5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView。

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、 ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。


7. SpringMVC常用的注解有哪些?


@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。

@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。

@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。


8. 谈谈你对Spring的AOP理解


  • AOP(Aspect-Oriented Programming,面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性。
  • Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么Spring AOP就会使用JDK动态代理去创建代理对象;而对于没有实现接口的对象,就无法使用JDK动态代理,转而使用CGlib动态代理生成一个被代理对象的子类来作为代理。


9. Spring AOP和AspectJ AOP有什么区别?


  • Spring AOP是属于运行时增强,而AspectJ是编译时增强。Spring AOP基于代理(Proxying),而AspectJ基于字节码操作(Bytecode Manipulation)。
  • Spring AOP已经集成了AspectJ,AspectJ应该算得上是Java生态系统中最完整的AOP框架了。AspectJ相比于Spring AOP功能更加强大,但是Spring AOP相对来说更简单。

如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择AspectJ,它比SpringAOP快很多。


10. 什么是通知呢?有哪些类型呢?


通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段。

Spring切面可以应用五种类型的通知:

  • before:前置通知,在一个方法执行前被调用。
  • after: 在方法执行之后调用的通知,无论方法执行是否成功。
  • after-returning: 仅当方法成功完成后执行的通知。
  • after-throwing: 在方法抛出异常退出时执行的通知。
  • around: 在方法执行之前和之后调用的通知。


11. 说说你对Spring的IOC是怎么理解的?


  • IOC就是控制反转,是指创建对象的控制权的转移。以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系。对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
  • 最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
  • Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。


12. 解释Spring支持的几种bean的作用域?


Spring容器中的bean可以分为5个范围:

  • singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。
  • prototype:为每一个bean请求提供一个实例。
  • request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
  • session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
  • global-session:全局作用域,global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。


13. Spring基于xml注入bean的几种方式?


(1)Set方法注入;

(2)构造器注入:①通过index设置参数的位置;②通过type设置参数类型;

(3)静态工厂注入;

(4)实例工厂;


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


这是一道相对有难度的题目,你不仅要回设计模式,还要知道每个设计模式在Spring中是如何使用的。

  • 简单工厂模式:Spring 中的 BeanFactory 就是简单工厂模式的体现。根据传入一个唯一的标识来获得 Bean 对象,但是在传入参数后创建还是传入参数前创建,要根据具体情况来定。
  • 工厂模式:Spring 中的 FactoryBean 就是典型的工厂方法模式,实现了 FactoryBean 接口的 bean是一类叫做 factory 的 bean。其特点是,spring 在使用 getBean() 调用获得该 bean 时,会自动调用该 bean 的 getObject() 方法,所以返回的不是 factory 这个 bean,而是这个 bean.getOjbect()方法的返回值。
  • 单例模式:在 spring 中用到的单例模式有: scope="singleton" ,注册式单例模式,bean 存放于Map 中。bean name 当做 key,bean 当做 value。
  • 原型模式:在 spring 中用到的原型模式有: scope="prototype" ,每次获取的是通过克隆生成的新实例,对其进行修改时对原有实例对象不造成任何影响。
  • 迭代器模式:在 Spring 中有个 CompositeIterator 实现了 Iterator,Iterable 接口和 Iterator 接口,这两个都是迭代相关的接口。可以这么认为,实现了 Iterable 接口,则表示某个对象是可被迭代的。Iterator 接口相当于是一个迭代器,实现了 Iterator 接口,等于具体定义了这个可被迭代的对象时如何进行迭代的。
  • 代理模式:Spring 中经典的 AOP,就是使用动态代理实现的,分 JDK 和 CGlib 动态代理。
  • 适配器模式:Spring 中的 AOP 中 AdvisorAdapter 类,它有三个实现:MethodBeforAdviceAdapter、AfterReturnningAdviceAdapter、ThrowsAdviceAdapter。Spring会根据不同的 AOP 配置来使用对应的 Advice,与策略模式不同的是,一个方法可以同时拥有多个Advice。Spring 存在很多以 Adapter 结尾的,大多数都是适配器模式。
  • 观察者模式:Spring 中的 Event 和 Listener。spring 事件:ApplicationEvent,该抽象类继承了EventObject 类,JDK 建议所有的事件都应该继承自 EventObject。spring 事件监听器:ApplicationListener,该接口继承了 EventListener 接口,JDK 建议所有的事件监听器都应该继承EventListener。
  • 模板模式:Spring 中的 org.springframework.jdbc.core.JdbcTemplate 就是非常经典的模板模式的应用,里面的 execute 方法,把整个算法步骤都定义好了。责任链模式:DispatcherServlet 中的 doDispatch() 方法中获取与请求匹配的处理器HandlerExecutionChain,this.getHandler() 方法的处理使用到了责任链模式。


15. Spring 框架中的单例 Bean 是线程安全的么?


Spring 框架并没有对单例 Bean 进行任何多线程的封装处理。

  • 关于单例 Bean 的线程安全和并发问题,需要开发者自行去搞定。
  • 单例的线程安全问题,并不是 Spring 应该去关心的。Spring 应该做的是,提供根据配置,创建单例 Bean 或多例 Bean 的功能。

当然,但实际上,大部分的 Spring Bean 并没有可变的状态,所以在某种程度上说 Spring 的单例Bean 是线程安全的。如果你的 Bean 有多种状态的话,就需要自行保证线程安全。最浅显的解决办法,就是将多态 Bean 的作用域(Scope)由 Singleton 变更为 Prototype。


16. Spring 是怎么解决循环依赖的?


整个流程大致如下:

  • 首先 A 完成初始化第一步并将自己提前曝光出来(通过 ObjectFactory 将自己提前曝光),在初始化的时候,发现自己依赖对象 B,此时就会去尝试 get(B),这个时候发现 B 还没有被创建出来;
  • 然后 B 就走创建流程,在 B 初始化的时候,同样发现自己依赖 C,C 也没有被创建出来;
  • 这个时候 C 又开始初始化进程,但是在初始化的过程中发现自己依赖 A,于是尝试 get(A)。这个时候由于 A 已经添加至缓存中(一般都是添加至三级缓存 singletonFactories),通过ObjectFactory 提前曝光,所以可以通过 ObjectFactory#getObject() 方法来拿到 A 对象。C 拿 到 A 对象后顺利完成初始化,然后将自己添加到一级缓存中;
  • 回到 B,B 也可以拿到 C 对象,完成初始化,A 可以顺利拿到 B 完成初始化。到这里整个链路就已经完成了初始化过程了。

关键字:三级缓存,提前曝光。


17. 说说事务的隔离级别


  • 未提交读(Read Uncommitted) :允许脏读,也就是可能读取到其他会话中未提交事务修改的数据提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read) :在同一个事务内的查询都是事务开始时刻一致的,Mysql的InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读(多个事务同时修改同一条记录,事务之间不知道彼此存在,当事务提交之后,后面的事务修改的数据将会覆盖前事务,前一个事务就像发生幻觉一样)
  • 可串行化(Serializable) :完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。
  • 不可重复读和幻读的区别主要是 : 解决不可重复读需要锁定了当前满足条件的记录,而解决幻读需要锁定当前满足条件的记录及相近的记录。比如查询某个商品的信息,可重复读事务隔离级别可以保证当前商品信息被锁定,解决不可重复读;但是如果统计商品个数,中途有记录插入,可重复读事务隔离级别就不能保证两个事务统计的个数相同。


18. 说说事务的传播级别


Spring事务定义了7种传播机制:

  1. PROPAGATION_REQUIRED:默认的Spring事物传播级别,若当前存在事务,则加入该事务,若不存在事务,则新建一个事务。
  2. PAOPAGATION_REQUIRE_NEW:若当前没有事务,则新建一个事务。若当前存在事务,则新建一个事务,新老事务相互独立。外部事务抛出异常回滚不会影响内部事务的正常提交。
  3. PROPAGATION_NESTED:如果当前存在事务,则嵌套在当前事务中执行。如果当前没有事务,则新建一个事务,类似于REQUIRE_NEW。
  4. PROPAGATION_SUPPORTS:支持当前事务,若当前不存在事务,以非事务的方式执行。
  5. PROPAGATION_NOT_SUPPORTED:以非事务的方式执行,若当前存在事务,则把当前事务挂起。
  6. PROPAGATION_MANDATORY:强制事务执行,若当前不存在事务,则抛出异常.
  7. PROPAGATION_NEVER:以非事务的方式执行,如果当前存在事务,则抛出异常。

Spring事务传播级别一般不需要定义,默认就是PROPAGATION_REQUIRED,除非在嵌套事务的情

况下需要重点了解。


19. Spring 事务实现方式


  • 编程式事务管理:这意味着你可以通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
  • 声明式事务管理:这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。


20. 事务三要素是什么?


数据源:表示具体的事务性资源,是事务的真正处理者,如MySQL等。

事务管理器:像一个大管家,从整体上管理事务的处理过程,如打开、提交、回滚等。

事务应用和属性配置:像一个标识符,表明哪些方法要参与事务,如何参与事务,以及一些相关属性如隔离级别、超时时间等。


21. 事务注解的本质是什么?


  • @Transactional 这个注解仅仅是一些(和事务相关的)元数据,在运行时被事务基础设施读取消费,并使用这些元数据来配置bean的事务行为。 大致来说具有两方面功能,一是表明该方法要参与事务,二是配置相关属性来定制事务的参与方式和运行行为
  • 声明式事务主要是得益于Spring AOP。使用一个事务拦截器,在方法调用的前后/周围进行事务性增强(advice),来驱动事务完成。
  • @Transactional注解既可以标注在类上,也可以标注在方法上。当在类上时,默认应用到类里的所有方法。如果此时方法上也标注了,则方法上的优先级高。 另外注意方法一定要是public的。



相关文章
|
6天前
|
XML Java 数据格式
Spring面试题pro版-3
Spring面试题pro版-3
18 0
|
6天前
|
设计模式 Java 数据库
Spring面试题系列-4
Spring面试题系列-4
17 1
|
15天前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
28 0
|
24天前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
32 1
|
1月前
|
缓存 前端开发 Java
Spring MVC 面试题及答案整理,最新面试题
Spring MVC 面试题及答案整理,最新面试题
90 0
|
1月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
111 0
|
1月前
|
负载均衡 Java API
Spring Cloud 面试题及答案整理,最新面试题
Spring Cloud 面试题及答案整理,最新面试题
138 1
|
1月前
|
Java Nacos Sentinel
Spring Cloud Alibaba 面试题及答案整理,最新面试题
Spring Cloud Alibaba 面试题及答案整理,最新面试题
207 0
|
2天前
|
安全 Java 数据库连接
[AIGC] Spring框架的基本概念和优势
[AIGC] Spring框架的基本概念和优势
|
2天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例