2021年初巨献!往年春招+秋招+校招+社招spring框架面试题合集分享,助你完胜金三银四!

前言

一眨眼不仅2020过完了,连2021的第一个假期元旦节也过完啦!相信大家现在已经都开始上班了,过完假期就得收心准备好自己接下来的工作以及生活了,现在已经是一月份了!接下来马上就是年假,年假一过完马上就是一年最重要的金三银四,所以说现在这段时间是学习充实自己的最好机会!之前一直有粉丝私信我让我总结一下spring的面试题,现在它来了,以下面试题涵盖了spring从初级到高级的内容,大家可以挑选自己感兴趣的部分阅读!

什么是 Spring 框架?

  • Spring 是⼀种轻量级开发框架,旨在提⾼开发⼈员的开发效率以及系统的可维护性
  • 我们⼀般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使⽤这些模块可以很⽅便地协助我们进⾏开发。这些模块是:核⼼容器、数据访问/集成,、Web、AOP(⾯向切⾯编程)、⼯具、消息和测试模块。⽐如:Core Container 中的 Core 组件是Spring 所有组件的核⼼,Beans 组件和 Context 组件是实现IOC和依赖注⼊的基础,AOP组件⽤来实现⾯向切⾯编程。

Spring 的 6 个特征:

  • 核⼼技术 :依赖注⼊(DI),AOP,事件(events),资源,i18n,验证,数据绑定,类型转换,SpEL。
  • 测试 :模拟对象,TestContext框架,Spring MVC 测试,WebTestClient。
  • 数据访问 :事务,DAO⽀持,JDBC,ORM,编组XML。
  • Web⽀持 : Spring MVC和Spring WebFlux Web框架。
  • 集成 :远程处理,JMS,JCA,JMX,电⼦邮件,任务,调度,缓存。
  • 语⾔ :Kotlin,Groovy,动态语⾔。

列举⼀些重要的Spring模块?

  • 下图对应的是 Spring4.x 版本。⽬前最新的5.x版本中 Web 模块的 Portlet 组件已经被废弃掉,同时增加了⽤于异步响应式处理的 WebFlux 组件。

  • Spring Core: 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注⼊功能。

  • Spring Aspects : 该模块为与AspectJ的集成提供⽀持。

  • Spring AOP :提供了⾯向切⾯的编程实现。

  • Spring JDBC : Java数据库连接。

  • Spring JMS :Java消息服务。

  • Spring ORM : ⽤于⽀持Hibernate等ORM⼯具。

  • Spring Web : 为创建Web应⽤程序提供⽀持。

  • Spring Test : 提供了对 JUnit 和 TestNG 测试的⽀持。

谈谈⾃⼰对于 Spring IoC 和 AOP 的理解

IoC

  • IoC(Inverse of Control:控制反转)是⼀种设计思想,就是 将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。 IoC 容器是 Spring⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。
  • 将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。 IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。在实际项⽬中⼀个 Service 类可能有⼏百甚⾄上千个类作为它的底层,假如我们需要实例化这个Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把⼈逼疯。如果利⽤IoC 的话,你只需要配置好,然后在需要的地⽅引⽤就⾏了,这⼤⼤增加了项⽬的可维护性且降低了开发难度

Spring IoC的初始化过程:

AOP

  • AOP(Aspect-Oriented Programming:⾯向切⾯编程)能够将那些与业务⽆关,却为业务模块所共同调⽤的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
  • Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDKProxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候Spring AOP会使⽤Cglib ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理,
    如下图所示:
  • 当然你也可以使⽤ AspectJ ,Spring AOP 已经集成了AspectJ ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框架了。
  • 使⽤ AOP 之后我们可以把⼀些通⽤功能抽象出来,在需要⽤到的地⽅直接使⽤即可,这样⼤⼤简化了
    代码量。我们需要增加新功能时也⽅便,这样也提⾼了系统扩展性。⽇志功能、事务管理等等场景都⽤到了 AOP 。

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 ,它⽐Spring AOP 快很多。

Spring 中的 bean 的作⽤域有哪些?

  • singleton : 唯⼀ bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建⼀个新的 bean 实例。
  • request : 每⼀次HTTP请求都会产⽣⼀个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每⼀次HTTP请求都会产⽣⼀个新的 bean,该bean仅在当前 HTTP session 内有效。
  • global-session: 全局session作⽤域,仅仅在基于portlet的web应⽤中才有意义,Spring5已经没有了。Portlet是能够⽣成语义代码(例如:HTML)⽚段的⼩型Java Web插件。它们基于portlet容器,可以像servlet⼀样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话

Spring 中的单例 bean 的线程安全问题了解吗?

  • ⼤部分时候我们并没有在系统中使⽤多线程,所以很少有⼈会关注这个问题。单例 bean 存在线程问
    题,主要是因为当多个线程操作同⼀个对象的时候,对这个对象的⾮静态成员变量的写操作会存在线程
    安全问题。

常⻅的有两种解决办法:

  • 在Bean对象中尽量避免定义可变的成员变量(不太现实)。
  • 在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的⼀种⽅式)。

@Component 和 @Bean 的区别是什么?

  • 作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法。
  • @Component 通常是通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中(我们可以使⽤@ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到 Spring 的bean 容器中)。 @Bean 注解通常是我们在标有该注解的⽅法中定义产⽣这个 bean, @Bean 告诉了Spring这是某个类的示例,当我需要⽤它的时候还给我。
  • @Bean 注解⽐ Component 注解的⾃定义性更强,⽽且很多地⽅我们只能通过 @Bean 注解来注册bean。⽐如当我们引⽤第三⽅库中的类需要装配到 Spring 容器时,则只能通过@Bean 来实现。

将⼀个类声明为Spring的 bean 的注解有哪些?

  • @Component :通⽤的注解,可标注任意类为 Spring 组件。如果⼀个Bean不知道属于哪个
    层,可以使⽤ @Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要⽤于数据库相关操作。
  • @Service : 对应服务层,主要涉及⼀些复杂的逻辑,需要⽤到 Dao层。
  • @Controller : 对应 Spring MVC 控制层,主要⽤户接受⽤户请求并调⽤ Service 层返回数据给前端⻚⾯。

Spring 中的 bean ⽣命周期?

  • Bean 容器找到配置⽂件中 Spring Bean 的定义。

  • Bean 容器利⽤ Java Reflection API 创建⼀个Bean的实例。

  • 如果涉及到⼀些属性值 利⽤ set() ⽅法设置⼀些属性值。

  • 如果 Bean 实现了 BeanNameAware 接⼝,调⽤ setBeanName() ⽅法,传⼊Bean的名字。

  • 如果 Bean 实现了 BeanClassLoaderAware 接⼝,调⽤ setBeanClassLoader() ⽅法,

  • 传⼊ ClassLoader 对象的实例。

  • 与上⾯的类似,如果实现了其他 *.Aware 接⼝,就调⽤相应的⽅法。

  • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执⾏ postProcessBeforeInitialization() ⽅法

  • 如果Bean实现了 InitializingBean 接⼝,执⾏ afterPropertiesSet() ⽅法。

  • 如果 Bean 在配置⽂件中的定义包含 init-method 属性,执⾏指定的⽅法。

  • 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执⾏ postProcessAfterInitialization() ⽅法

  • 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接⼝,执⾏ destroy() ⽅
    法。

  • 当要销毁 Bean 的时候,如果 Bean 在配置⽂件中的定义包含 destroy-method 属性,执⾏指定的⽅法。

说说⾃⼰对于 Spring MVC 了解?

MVC 是⼀种设计模式,Spring MVC 是⼀款很优秀的 MVC 框架。Spring MVC 可以帮助我们进⾏更简洁的Web层的开发,并且它天⽣与 Spring 框架集成。Spring MVC 下我们⼀般把后端项⽬分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台⻚⾯)。

Spring MVC 的简单原理图如下:

SpringMVC ⼯作原理了解吗?

流程说明:

  • 客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。
  • DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。
  • 解析到对应的 Handler (也就是我们平常说的 Controller 控制器)后,开始由
    HandlerAdapter 适配器处理。
  • HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。
  • 处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象, View是个逻辑上的 View 。
  • ViewResolver 会根据逻辑 View 查找实际的 View 。
  • DispaterServlet 把返回的 Model 传给 View (视图渲染)。
  • 把 View 返回给请求者(浏览器)

Spring 框架中⽤到了哪些设计模式?

  • ⼯⼚设计模式 : Spring使⽤⼯⼚模式通过 BeanFactory 、 ApplicationContext 创建bean 对象。
  • 代理设计模式 : Spring AOP 功能的实现。
  • 单例设计模式 : Spring 中的 Bean 默认都是单例的。
  • 包装器设计模式 : 我们的项⽬需要连接多个数据库,⽽且不同的客户在每次访问中根据需要会
  • 去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的⼀个应⽤。
  • 适配器模式 :Spring AOP 的增强或通知(Advice)使⽤到了适配器模式、spring MVC 中也是⽤到了适配器模式适配 Controller 。

Spring 管理事务的⽅式有⼏种?

  • 编程式事务,在代码中硬编码。(不推荐使⽤)
  • 声明式事务,在配置⽂件中配置(推荐使⽤)

声明式事务⼜分为两种:

  • 基于XML的声明式事务
  • 基于注解的声明式事务

Spring 事务中的隔离级别有哪⼏种?

  • TransactionDefinition.ISOLATION_DEFAULT: 使⽤后端数据库默认的隔离级别,Mysql 默认采⽤的 REPEATABLE_READ隔离级别 Oracle 默认采⽤的 READ_COMMITTED隔离级别.
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  • TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣
  • TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
  • TransactionDefinition.ISOLATION_SERIALIZABLE: 最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该级别可以防⽌脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会⽤到该级别。

Spring 事务中哪⼏种事务传播⾏为?

⽀持当前事务的情况:

  • TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。
  • TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
  • TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不⽀持当前事务的情况:

  • TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER: 以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。

其他情况:

  • TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于
  • TransactionDefinition.PROPAGATION_REQUIRED。

总结

感谢你看到这里,文章有什么不足还请指正,觉得文章对你有帮助的话记得给我点个三连!

另外我这里准备了一些Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等送你!有需要的朋友点这里备注csdn自行下载即可,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

猜你喜欢

转载自blog.csdn.net/weixin_53170315/article/details/112138466