一、为什么要使用 spring?
spring 是一个开源的轻量级 JavaBean 容器框架。使用 JavaBean 代替 EJB ,并提供了丰富的企业应用功能,降低应用开发的复杂性。
- 轻量:非入侵性的、所依赖的东西少、资源占用少、部署简单,不同功能选择不同的 jar 组合
- 容器:工厂模式实现对 JavaBean 进行管理,通过控制反转(IOC)将应用程序的配置和依赖性与应用代码分开
- 松耦合:通过 xml 配置或注解即可完成 bean 的依赖注入
- AOP:通过 xml 配置 或注解即可加入面向切面编程的能力,完成切面功能,如:日志,事务...的统一处理
- 方便集成:通过配置和简单的对象注入即可集成其他框架,如 Mybatis、Hibernate、Shiro...
- 丰富的功能:JDBC 层抽象、事务管理、MVC、Java Mail、任务调度、JMX、JMS、JNDI、EJB、动态语言、远程访问、Web Service...
二、解释一下什么是 aop?
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
三、解释一下什么是 ioc?
ioc:Inversionof Control(中文:控制反转)是 spring 的核心,对于 spring 框架来说,就是由 spring 来负责控制对象的生命周期和对象间的关系。 简单来说,控制指的是当前对象对内部成员的控制权;控制反转指的是,这种控制权不由当前对象管理了,由其他(类,第三方容器)来管理。
四、spring 有哪些主要模块?
Spring有七大功能模块,分别是Spring Core,AOP,ORM,DAO,MVC,WEB,Context。
- Spring Core:Core模块是Spring的核心类库,Spring的所有功能都依赖于该类库,Core主要实现IOC功能,Sprign的所有功能都是借助IOC实现的。
- AOP:AOP模块是Spring的AOP库,提供了AOP(拦截器)机制,并提供常用的拦截器,供用户自定义和配置。
- ORM:Spring 的ORM模块提供对常用的ORM框架的管理和辅助支持,Spring支持常用的Hibernate,ibtas,jdao等框架的支持,Spring本身并不对ORM进行实现,仅对常见的ORM框架进行封装,并对其进行管理
- DAO模块:Spring 提供对JDBC的支持,对JDBC进行封装,允许JDBC使用Spring资源,并能统一管理JDBC事物,并不对JDBC进行实现。(执行sql语句)
- WEB模块:WEB模块提供对常见框架如Struts1,WEBWORK(Struts 2),JSF的支持,Spring能够管理这些框架,将Spring的资源注入给框架,也能在这些框架的前后插入拦截器。
- Context模块:Context模块提供框架式的Bean访问方式,其他程序可以通过Context访问Spring的Bean资源,相当于资源注入。
- MVC模块:WEB MVC模块为Spring提供了一套轻量级的MVC实现,在Spring的开发中,我们既可以用Struts也可以用Spring自己的MVC框架,相对于Struts,Spring自己的MVC框架更加简洁和方便。
五、spring 常用的注入方式有哪些?
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入( 采用反射的方式,通过构造方法来完成注入**),setter注入(** 采用反射的方式,通过构造方法来完成注入**),基于注解的注入(** 常用的有"@AutoWried"和"@Resource")
六、spring 中的 bean 是线程安全的吗?
Spring容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性 ,但是具体情况还是要结合Bean的作用域来讨论。
- 对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。
- 对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。
- 有状态Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。
- 无状态Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。
对于有状态的bean(比如Model和View),就需要自行保证线程安全,最浅显的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”。
也可以采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。
七、spring 支持几种 bean 的作用域?
- singleton:单例模式,在整个Spring IoC容器中,使用 singleton 定义的 bean 只有一个实例
- prototype:原型模式,每次通过容器的getbean方法获取 prototype 定义的 bean 时,都产生一个新的 bean 实例
- request:对于每次 HTTP 请求,使用 request 定义的 bean 都将产生一个新实例,即每次 HTTP 请求将会产生不同的 bean 实例。
- session:同一个 Session 共享一个 bean 实例。
- global-session:同 session 作用域不同的是,所有的Session共享一个Bean实例。
只有在 Web 应用中使用Spring时,request、session、global-session 作用域才有效
八、spring 自动装配 bean 有哪些方式?
spring 配置文件中
- default - 默认的方式和 "no" 方式一样
- no - 不自动装配,需要使用 节点或参数
- byName - 根据名称进行装配
- byType - 根据类型进行装配
- constructor - 根据构造函数进行装配
九、spring 事务实现方式有哪些?
****编辑
Spring提供了编程式事务和声明式事务两种实现方式,
编程式事务: 允许用户在代码中精确定义事务的边界,
声明式事务(基于AOP): 有助于用户将操作与事务规则进行解耦。
简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。
十、说一下 spring 的事务隔离?
spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致 (越往下隔离级别越高,花费越大):
- read uncommited 未提交读:是最低的事务隔离级别。事务未提交前,数据就可被其他事务读取 --> 会造成:脏读、不可重复读、幻读
- read commited 提交读:一个事务提交后才能被其他事务读取到,SQL server 的默认级别 --> 会造成:不可重复读、幻读
- repeatable read 可重复读:保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据,MySQL 的默认级别 --> 会造成: 幻读。
- serializable 序列化:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。该隔离级别能防止脏读、不可重复读、幻读。
脏读、不可重复读、幻象读
- 脏读:表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。因为这个记录 A还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
- 不可重复读:指在一个事务内,多次读同一数据,但不一样。例如,事务1 读取 记录A, 事务1 还没有执行结束;此时另外一个 事务2 也访问 记录A,并修改了记录A。 那么在事务1 第两次读取记录A时,读到的数据可能是不一样的。这种情况被称为是不可重复读。
- 幻象读:指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。
十一、说一下 spring mvc 运行流程?
****编辑
执行流程:
- 用户向服务器发送请求,请求被 Spring 前端控制 Servelt DispatcherServlet 捕获(捕获)
- DispatcherServlet对请求 URL进行解析,得到请求资源标识符(URI)。然后根据该 URI,调用 HandlerMapping获得该Handler配置的所有相关的对象(包括 Handler对象以及 Handler对象对应的拦截器),最后以 HandlerExecutionChain对象的形式返回;(查找 handler)
- DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。 提取Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller), Handler执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象(执行 handler)
- DispatcherServlet 根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver) (选择 ViewResolver)
- 通过 ViewResolver 结合 Model 和 View,来渲染视图,DispatcherServlet 将渲染结果返回给客户端。(渲染返回)
快速记忆技巧:
核心控制器捕获请求、查找Handler、执行Handler、选择ViewResolver,通过ViewResolver渲染视图并返回
十二、spring mvc 有哪些组件?
- 前端控制器(DispatcherServlet)
- 处理器映射器(HandlerMapping)
- 处理器适配器(HandlerAdapter)
- 拦截器(HandlerInterceptor)
- 语言环境处理器(LocaleResolver)
- 主题解析器(ThemeResolver)
- 视图解析器(ViewResolver)
- 文件上传处理器(MultipartResolver)
- 异常处理器(HandlerExceptionResolver)
- 数据转换(DataBinder)
- 消息转换器(HttpMessageConverter)
- 请求转视图翻译器(RequestToViewNameTranslator)
- 页面跳转参数管理器(FlashMapManager)
- 处理程序执行链(HandlerExecutionChain)
十三、@RequestMapping 的作用是什么?
- **@RequestMapping ** 是一个用来处理请求地址映射的注解,可用于类或者方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
- **@RequestMapping ** 注解有六个属性:
- value:指定请求的实际地址,指定的地址可以是URI Template模式。
- method:指定请求的method类型,GET、POST、PUT、DELETE等。
- consumes:指定处理请求的提交内容类型(Content-Type),例如application/json,text/html。
- produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
- params:指定request中必须包含某些参数值才让该方法处理。
- headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。
十四、@Autowired 的作用是什么?
- @Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
- @Autowired 默认是按照类去匹配,配合 @Qualifier 指定按照名称去装配 bean。
注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!
注:此博客只是为了记忆相关知识点,大部分为网络上的文章,在此向各个文章的作者表示感谢!
标题:Java 常见的面试题(Spring/Spring MVC)
作者:wangjing
地址:https://www.codedblogs.cn/articles/2024/04/12/1712888868582.html