Spring 面试整理

1、说一下 spring mvc 运行流程?

  • spring mvc 先将请求发送给 DispatcherServlet。
  • DispatcherServlet 查询一个或多个 HandlerMapping,找到处理请求的 Controller。 DispatcherServlet 再把请求提交到对应的 Controller。
  • Controller 进行业务逻辑处理后,会返回一个ModelAndView。
  • Dispathcher 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 对象指定的视图对象。 视图对象负责渲染返回给客户端。

2、说一下 spring 的事务隔离?

spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致:

  • ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
  • ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);
  • ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
  • ISOLATIONREPEATABLEREAD:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
  • ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。 脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。 不可重复读 :是指在一个事务内,多次读同一数据。 幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

3、spring 自动装配 bean 有哪些方式?

  • no:默认值,表示没有自动装配,应使用显式 bean 引用进行装配。
  • byName:它根据 bean 的名称注入对象依赖项。
  • byType:它根据类型注入对象依赖项。 构造函数:通过构造函数来注入依赖项,需要设置大量的参数。

autodetect:容器首先通过构造函数使用 autowire 装配,如果不能,则通过 byType 自动装配。

4、spring 支持几种 bean 的作用域?

spring 支持 5 种作用域,如下:

  • singleton:spring ioc 容器中只存在一个 bean 实例,bean 以单例模式存在,是系统默认值; prototype:每次从容器调用 bean 时都会创建一个新的示例,既每次 getBean()相当于执行 new Bean()操作;
  • Web 环境下的作用域:
  • request:每次 http 请求都会创建一个 bean;
  • session:同一个 http session 共享一个 bean 实例;
  • global-session:用于 portlet 容器,因为每个 portlet 有单独的 session,globalsession 提供一个全局性的 http session。

5、spring 中的 bean 是线程安全的吗?

spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。 实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。 有状态就是有数据存储功能。 无状态就是不会保存数据。

6、谈谈你对SpringIOC和DI的理解?

首先,SpringIOC,全称控制反转(InversionofControl)。 在传统的Java程序开发中,我们只能通过new关键字来创建对象,这种导致程序中对象的依赖关系比较复杂,耦合度较高。 而IOC的主要作用是实现了对象的管理,也就是我们把设计好的对象交给了IOC 容器控制,然后在需要用到目标对象的时候,直接从容器中去获取。 有了IOC容器来管理Bean以后,相当于把对象的创建和查找依赖对象的控制权交给了容器,这种设计理念使得对象与对象之间是一种松耦合状态,极大提升了程序的灵活性以及功能的复用性。 然后,DI表示依赖注入,也就是对于IOC容器中管理的Bean,如果Bean之间存在依赖关系,那么IOC容器需要自动实现依赖对象的实例注入,通常有三种方法来描述Bean之间的依赖关系。 接口注入 setter注入 构造器注入 另外,为了更加灵活的实现Bean实例的依赖注入,Spring还提供了@Resource和@Autowired这两个注解。 分别是根据bean的id和bean的类型来实现依赖注入。

7、Spring Cloud 如何实现服务的注册

服务注册的实现方式 Spring Cloud提供了几种服务注册的实现方式,包括:

Eureka:Netflix公司开源的、最为流行的一种服务注册中心;

Consul:由Hashicorp公司开发的一种服务发现组件,支持多数据中心;

ZooKeeper:由Apache项目开发的一种分布式协调框架。 Eureka的工作原理 注册中心 注册中心是一个基于REST的服务,主要实现服务注册、服务续约、服务下线以及查询功能。

Eureka Server接收服务实例的注册请求,并将服务实例信息存储在内存中(HashMap)。当Eureka Server收到服务实例的续约请求时,会更新服务实例在内存中的信息,避免服务实例过期失效。也可以通过URL获取注册中心中所有可用的服务。 服务实例 服务实例启动后会向Eureka Server发送注册请求,告知Eureka Server自己的地址(ip:port)、服务名、健康状态以及一些元数据。同时服务实例会以心跳的方式向Eureka Server发送服务续约请求,在规定时间内没有接收到续约请求,则视为服务实例失效。

8、Spring Boot如何解决跨域问题?

跨域是指在浏览器中,当一个网页的脚本试图去访问另一个网页的资源时,如果这两个网页的域名、协议或端口不一致,就会发生跨域问题。 JSONP(JSON with Padding):JSONP是一种利用script标签的src属性不受同源策略限制的特点来进行跨域数据传输的方法。通过动态创建script标签,并指定src属性为跨域请求的URL,服务器返回的数据会被包裹在回调函数中,通过执行回调函数来获取数据。 CORS(跨域资源共享):CORS是一种标准的跨域解决方案,它通过在服务器端设置响应头来允许指定的域名进行跨域访问。在服务器端设置Access-Control-Allow-Origin字段,指定允许的域名或通配符(*)来解决跨域问题。 代理服务器:可以在同源的情况下,设置一个代理服务器,将跨域请求转发到目标服务器,再将结果返回给浏览器。客户端通过访问同源的代理服务器来避免跨域问题。 WebSocket:WebSocket是一种全双工通信协议,不受同源策略的限制,可以在不同域名间进行跨域通信。 postMessage:使用HTML5中的postMessage方法,可以实现不同窗口(甚至不同域名)之间的跨域通信。 在Spring Boot项目中可以通过配置来解决跨域问题,在Spring Boot的配置类中添加一个跨域配置的Bean。

9、Spring Boot 核心配置文件

1、application.properties application.properties 是基于属性文件的配置格式,支持 key-value 形式的键值对。在 Spring Boot 中,可以在 application.properties 文件中配置各种应用程序属性,如端口号、数据库连接、日志级别等等。

2、application.yml application.yml 是基于 YAML 格式的配置文件,支持层级结构的配置形式,可以更加清晰地表达配置项之间的关系。与 application.properties 相比,application.yml 更易读、易维护,也更加灵活。

3、常用配置项 以下是一些常用的 Spring Boot 配置项: 服务器配置 server.port:应用程序监听的端口号,默认为 8080; server.servlet.context-path:应用程序的上下文路径,默认为空; server.tomcat.access-log-enabled:是否开启访问日志,默认为 false。

10、什么是Spring Boot Stater?

Spring Boot Starter是Spring Boot框架中的一个重要概念,它是一种可重用的模块,用于快速启动和配置Spring应用程序。Spring Boot Starter可以包含多个依赖项,这些依赖项可以自动配置和集成到应用程序中,从而简化了应用程序的开发和部署。Spring Boot Starter可以根据应用程序的需求进行选择和组合,使得应用程序的构建更加灵活和高效。

11、Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?

答:Spring支持编程式事务管理和声明式事务管理。许多Spring框架的用户选择声明式事务管理,因为这种方式和应用程序的关联较少,因此更加符合轻量级容器的概念。声明式事务管理要优于编程式事务管理,尽管在灵活性方面它弱于编程式事务管理,因为编程式事务允许你通过代码控制业务。 事务分为全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器JTA支持(如WebLogic、WildFly等)。局部事务和底层采用的持久化方案有关,例如使用JDBC进行持久化时,需要使用Connetion对象来操作事务;而采用Hibernate进行持久化时,需要使用Session对象来操作事务。

12、Spring Bean 生命周期的执行流程

Spring 生命周期全过程大致分为五个阶段:
  • 创建前准备阶段;
  • 创建实例阶段;
  • 依赖注入阶段;
  • 容器缓存阶段;
  • 销毁实例阶段;
13、Spring 是如何解决循环依赖问题的?
我们都知道,如果在代码中,将两个或多个 Bean 互相之间持有对方的引用就会
发生循环依赖。循环的依赖将会导致注入死循环。这是 Spring 发生循环依赖的
原因。
循环依赖有三种形态:
第一种互相依赖: A 依赖 B B 又依赖 A ,它们之间形成了循环依赖。
第二种三者间依赖: A 依赖 B B 依赖 C C 又依赖 A ,形成了循环依赖。
第三种是自我依赖: A 依赖 A 形成了循环依赖。
Spring 中设计了三级缓存来解决循环依赖问题,当我们去调用 getBean() 方法
的时候, Spring 会先从一级缓存中去找到目标 Bean ,如果发现一级缓存中没有
便会去二级缓存中去找,而如果一、二级缓存中都没有找到,意味着该目标 Bean
还没有实例化。于是, Spring 容器会实例化目标 Bean PS :刚初始化的 Bean
称为早期 Bean ) 。然后,将目标 Bean 放入到二级缓存中,同时,加上标记是
否存在循环依赖。如果不存在循环依赖便会将目标 Bean 存入到二级缓存,否则,
便会标记该 Bean 存在循环依赖,然后将等待下一次轮询赋值,也就是解析
@Autowired 注解。等 @Autowired 注解赋值完成后,会将目标 Bean 存入到一
级缓存。
Spring 一级缓存中存放所有的成熟 Bean ,二级缓存中存放所有的早期 Bean
先取一级缓存,再去二级缓存。
14、Spring Boot 的约定优于配置,你的理解是什么?
我从 4 个点方面来回答。
首先,约定优于配置是一种软件设计的范式,它的核心思想是减少软件开发人员
对于配置项的维护,从而让开发人员更加聚焦在业务逻辑上。
Spring Boot 就是约定优于配置这一理念下的产物,它类似于 Spring 框架下的一
个脚手架,通过 Spring Boot ,我们可以快速开发基于 Spring 生态下的应用程序。
基于传统的 Spring 框架开发 web 应用,我们需要做很多和业务开发无关并且只
需要做一次的配置,比如 管理 jar 包依赖 、web.xml 维护 、Dispatch-Servlet.xml 配置项维护
应用部署到 Web 容器。第三方组件集成到 Spring IOC 容器中的配置项维护。
而在 Spring Boot 中,我们不需要再去做这些繁琐的配置, Spring Boot 已经自
动帮我们完成了,这就是约定由于配置思想的体现。
Spring Boot 约定由于配置的体现有很多,比如
Spring Boot Starter 启动依赖,它能帮我们管理所有 jar 包版本
如果当前应用依赖了 spring mvc 相关的 jar ,那么 Spring Boot 会自动内置 Tomcat
容器来运行 web 应用,我们不需要再去单独做应用部署。
Spring Boot 的自动装配机制的实现中,通过扫描约定路径下的 spring.factories
文件来识别配置类,实现 Bean 的自动装配。
默认加载的配置文件 application.properties 等等。
总的来说,约定优于配置是一个比较常见的软件设计思想,它的核心本质都是为
了更高效以及更便捷的实现软件系统的开发和维护。
15、Spring Boot 中自动装配机制的原理
自动装配,简单来说就是自动把第三方组件的 Bean 装载到 Spring IOC 器里面,
不需要开发人员再去写 Bean 的装配配置。
Spring Boot 应用里面,只需要在启动类加上 @SpringBootApplication 注解就
可以实现自动装配。
@SpringBootApplication 是 一 个 复 合 注 解 , 真 正 实 现 自 动 装 配 的 注 解 是
@EnableAutoConfiguration
自动装配的实现主要依靠三个核心关键技术。
引入 Starter 启动依赖组件的时候,这个组件里面必须要包含 @Configuration
置类,在这个配置类里面通过 @Bean 注解声明需要装配到 IOC 容器的 Bean
象。
这个配置类是放在第三方的 jar 包里面,然后通过 SpringBoot 中的约定优于配置
思想,把这个配置类的全路径放在 classpath:/META-INF/spring.factories 文件中。
这样 SpringBoot 就可以知道第三方 jar 包里面的配置类的位置,这个步骤主要是
用到了 Spring 里面的 SpringFactoriesLoader 来完成的。
SpringBoot 拿到所第三方 jar 包里面声明的配置类以后,再通过 Spring 提供的
ImportSelector 接口,实现对这些配置类的动态加载。
在我看来, SpringBoot 是约定优于配置这一理念下的产物,所以在很多的地方,
都会看到这类的思想。它的出现,让开发人员更加聚焦在了业务代码的编写上,
而不需要去关心和业务无关的配置。
其实,自动装配的思想,在 SpringFramework3.x 版本里面的 @Enable 注解,就
有了实现的雏形。 @Enable 注解是模块驱动的意思,我们只需要增加某个
@Enable 注解,就自动打开某个功能,而不需要针对这个功能去做 Bean 的配
置, @Enable 底层也是帮我们去自动完成这个模块相关 Bean 的注入。
16、Spring 中事务的传播行为有哪些?
首选,所谓的事务传播行为,就是多个声明了事务的方法相互调用的时候,这个
事务应该如何传播。
比如说, methodA() 调用 methodB() ,两个方法都显示的开启了事务。
那么 methodB() 是开启一个新事务,还是继续在 methodA() 这个事务中执行?就
取 决 于 事 务 的 传 播 行 为 。
Spring 中,定义了 7 种事务传播行为。
  • REQUIRED:默认的 Spring 事物传播级别,如果当前存在事务,则加入这个事
务,如果不存在事务,就新建一个事务。
  • REQUIRE_NEW:不管是否存在事务,都会新开一个事务,新老事务相互独立。
外部事务抛出异常回滚不会影响内部事务的正常提交。
  • NESTED:如果当前存在事务,则嵌套在当前事务中执行。如果当前没有事务,
则新建一个事务,类似于 REQUIRE_NEW
  • SUPPORTS:表示支持当前事务,如果当前不存在事务,以非事务的方式执行。
  • NOT_SUPPORTED:表示以非事务的方式来运行,如果当前存在事务,则把当
前事务挂起。
  • MANDATORY:强制事务执行,若当前不存在事务,则抛出异常.
  • NEVER:以非事务的方式执行,如果当前存在事务,则抛出异常。
Spring 事务传播级别一般不需要定义,默认就是 PROPAGATION_REQUIRED
除非在嵌套事务的情况下需要重点了解。
17、Spring 中有哪些方式可以把 Bean 注入IOC 容器?
好的,把 Bean 注入到 IOC 容器里面的方式有 7 种方式
使用 xml 的方式来声明 Bean 的定义, Spring 容器在启动的时候会加载并解析这
xml ,把 bean 装载到 IOC 容器中。
使用 @CompontScan 注解来扫描声明了 @Controller @Service @Repository
@Component 注解的类。
使用 @Configuration 注解声明配置类,并使用 @Bean 注解实现 Bean 的定义,
这种方式其实是 xml 配置方式的一种演变,是 Spring 迈入到无配置化时代的里
程碑。
使用 @Import 注解,导入配置类或者普通的 Bean
使 用 FactoryBean 工 厂 bean , 动 态 构 建 一 个 Bean 实 例 , Spring Cloud
OpenFeign 里面的动态代理实例就是使用 FactoryBean 来实现的。
实现 ImportBeanDefinitionRegistrar 接口,可以动态注入 Bean 实例。这个在
Spring Boot 里面的启动注解有用到。
实现 ImportSelector 接口,动态批量注入配置类或者 Bean 对象,这个在 Spring
Boot 里面的自动装配机制里面有用到。
以上就是我对这个问题的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值