Spring面试题(2022)

在这里插入图片描述

1、说说你对spring的理解,或者说下什么是spring?

分析:主要考察求职者对spring的整体掌握度,附带考察求职者思维缜密度、表达能力等,面对这类半开放型题目,我们只需要围着理论依据+实际使用经验,展开描述即可,千万不要去背官方的甲骨文,要附带自己的理解和见解。

答:spring是一款主流的非侵入式设计、轻量级web框架,最大特点是面向Java bean编程,降低了类之间的耦合性,
其IOC、DI是spring 容器的核心,为bean提供了容身之处以及帮我们管理对象及其依赖关系,也为spring后续发展奠定基石,
同时还集成了优秀理念AOP、MCV等,主要包含CORE、ORM、ContextWebWeb MVC、AOP、DAO等组件,一定程度上简化了web开发。

2、说说spring都有哪些模块(spring的模块有哪些)?

分析:主要考察求职者对spring 各模块熟悉程度

答:Spring Core:主要提供IOC和DI功能,是其他模块的基石。

Spring AOP:提供面向切面的编程实现,支持JDK与CGLIB

Spring JDBC:Java数据库连接

Spring JMS:Java消息服务

Spring ORM:支持扩展Hibernate、mybatis等ORM工具

Spring Web:为创建Web应用程序提供支持

Spring Test:提供了对JUnit和TestNG测试的支持

Spring tx:事务管理

3、怎么理解spring的ioc(对spring ioc的理解和使用)?

分析:考察对spring ioc的理解,要回答出什么是ioc,spring怎么实现的ioc

答:理解:ioc官方释义为控制反转,按照我的理解就是转让控制权,就拿创建Java对象来说,没有ioc之前,我们创建对象,需要显示的new,再通过构造参数、get、set赋值,然后再使用,有了spring ioc之后,我们就不需要亲力亲为,我们只需要告诉spring要用哪个对象即可,不用我们在代码里new了,对象的控制权由用户转让给了spring容器。

使用:使用spring ioc 主要分为以下两个步骤:

1、指定需要放入spring容器中的bean,spring提供了xml + bean标签和注解两种方式供我们使用,指定后,spring会通收集对象信息封装成BeanDefinition,然后通过过反射创建bean,最后放入容器里供我们使用

2、指定需要使用spring容器的哪个bean。spring提供了Autowired(按类型注入)注解,同时支持jdk的Resource(按名称注入)注解。

4、Spring的Bean是如何创建的?

分析:考察对spring bean创建过程的掌握,出现关键词 BeanDefinitionReader、BeanDefinition、BeanDefinitionWrapper、反射、一级缓存

答:1、根据Context类型(xml、注解)初始化BeanDefinitionReader,通过BeanDefinitionReader确认哪些Bean需要被初始化,然后将一个个的bean信息封装层BeanDefinition,最后在包装成BeanDefinitionWrapper,放入到BeanDefinitionRegister对应map中。

2、遍历所有BeanDefinition,按照 实例化-> 依赖注入->初始化->AOP的顺序通过反射去创建bean对象

3、将创建完成的Bean放入到一级缓存中存储,供用户使用。

5、spring注入bean的方式有哪些(列举下你使用过的注入Bean的方式)?

①配置类: @Configuration+@Bean

②注解配合:@Component + @ComponentScan

③实现ImportSelector接口往spring容器中批量注入Bean

④实现ImportBeanDefinitionRegistrar接口,将bean封装成BeanDfinition往容器中注入,从而实现注入bean

⑤实现FactoryBean接口可以往Spring容器中自定义Bean

6、说说bean的生命周期?

分析:考察对bean的生命周期掌握,springBean的生命周期就是bean的创建过程,按照这个过程说出来就好

答:springBean的生命周期就是bean的创建过程,按照大的流程分的话为:实例化->属性注入->初始化->销毁,spring为了用户能更好的管理bean的生命周期,因此在这4个步骤中开放了大量的接口,让用户可以对bean的一些行为或者属性进行变更,因此完整的Bean的生命周期如下:

  • 1、实例化
    实例化一个Bean,即new。
  • 2、IOC依赖注入
    按照Spring上下文对实例化的Bean进行配置。
  • 3、setBeanName实现
    如果这个Bean已经实现了BeanNameAware接口,就会调用它实现的setBeanName(String)方法,此处传递的是Spring配置文件中Bean的id值。
  • 4、setBeanFactory实现
    如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(BeanFactory)方法,传递的是Spring工厂自身。
  • 5、setApplicationContext实现
    如果这个Bean实现了ApplicationContextAware接口,会调用它实现的setApplicationContext(ApplicationContext)方法,传递的是Spring的上下文。
  • 6、postProcessBeforeInitialization实现-初始化预处理
    如果这个Bean实现了BeanPostProcessor接口,将会调用它实现的postProcessBeforeInitialization(Object obj,String s)方法。BeanPostProcessor被用作Bean内容修改,并且由于这个是在Bean初始化结束的时候调用的这个方法,也可以被用于内存或缓存技术。
  • 7、init-method
    如果这个bean在Spring配置文件中配置了init-method属性,会自动调用其配置的初始化方法
  • 8、postProcessAfterInitialization
    如果这个Bean实现了BeanPostProcessor接口,将会调用它实现的postProcessAfterInitialization(Object obj,String s)方法。
    以上工作完成以后就可以应用这个Bean了。
  • 9、Destory过期自动清理
    当Bean不再需要时,如果这个Bean实现了DisposableBean这个接口,会调用其实现的.destory()方法
  • 10、destory-method
    如果这个bean在Spring配置文件中配置了destory-method属性,会自动调用其配置的销毁方法

在这里插入图片描述

7、Spring常用的设计模式有哪些?

分析:考察对设计模式的理解,spring 用到的设计模式

答:模板方法设计模式Spring中jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的 类,
它们就使用到模板模式。

单例设计模式Spring中bean的默认作用域就是singleton。spring的一级缓存就是使用的容器式单例

代理设计模式Spring AOP就是基于动态代理的。如果要代理的对象,实现了某个接口,那么Spring AOP 会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用JDK Proxy去进行代理了,这 时候Spring AOP会使用Cglib,这时候Spring AOP会使用Cglib生成一个被代理对象的子类来作为代理。

工厂设计模式Spring使用工厂模式可以通过BeanFactory或ApplicationContext创建bean对象

观察者设计模式Spring事件驱动模型就是观察者模式很经典的应用。 spring的事件流程:

  1)定义一个事件: 实现一个继承自 ApplicationEvent,并且写相应的构造函数 
  2)定义一个事件监听者:实现 ApplicationListener 接口,重写 onApplicationEvent() 方法 
  3)使用事件发布者发布消息: 可以通过 ApplicationEventPublisherpublishEvent() 方法发布消息

策略设计模式Spring 框架的资源访问接口就是基于策略设计模式实现的

装饰者设计模式:装饰者设计模式可以动态地给对象增加些额外的属性或行为。相比于使用继承,
装饰者 模式更加灵活 Spring 中配置DataSource的时候,DataSource可能是不同的数据库和数据源。
我们能否根据客户的需求在 少修改原有类的代码下切换不同的数据源?这个时候据需要用到装饰者模式。

适配器设计模式:适配器模式使得接口不兼容的那些类可以一起工作,其别名为包装器 在Spring MVC中,
DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler,解析 到对应的Handler
(也就是我们常说的Controller控制器)后,开始由HandlerAdapter适配器处理

8、BeanFactory和Context(ApplicationContext)的区别

分析:考察BeanFactory与Context的区别,需要掌握BeanFactory,与Context,BeanFactory是bean管理的最基础类,功能最简单。

答:因为 ApplicationContext 包含 BeanFactory 的所有功能,所以通常建议在普通BeanFactory中使用。 BeanFactory :延迟注入,相比于ApplicationContext 来说会占用更少的内存,程序启动速度更快。ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了 最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多 功能,所以一般开发人员使ApplicationContext会更多

9、spring是如何解决循环依赖的?

什么是循环依赖

从字面上来理解就是A依赖B的同时B也依赖了A,就像下面这样
在这里插入图片描述
体现到代码层次就是这个样子

@Component
public class A {
    // A中注入了B
    @Autowired
    private B b;
}

@Component
public class B {
    // B中也注入了A
    @Autowired
    private A a;
}

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

10. 为什么需要三级缓存,用二级缓存不行吗?

Spring 需要三级缓存的目的是为了在没有循环依赖的情况下,延迟代理对象的创建,使 Bean 的创建符合 Spring 的设计原则。

通过debug源码发现,第三级缓存里面存放的是singletonFactory,所以如果只有两级缓存的话,
二级缓存放的就应该是调用singletonFactory.getObject()拿到的bean。到这里,假如不存在AOP的话是完全没有问题的,
如果存在AOP,那么二级缓存里面放的就必须是代理后的bean,因为Spring事先并不知道是否存在循环依赖,
所以只能都放代理后的bean(循环依赖的情况下必须提前创建代理对象),这个时候问题就来了,如果不存在循环依赖,
又提前创建了代理对象,就不符合Spring延迟创建代理对象的设计原则了,这个问题二级缓存是没办法解决的,必须依赖三级缓存。
通过源码也可以看到getEarlyBeanReference这个方法,只有在存在循环依赖的情况下,这个方法才会被调用,
而提前创建代理对象正是在这里创建的,所以三级缓存完美的解决了这个问题。

在这里插入图片描述

10、spring能解决那些循环依赖、不能解决那些循环依赖,为什么?

答:①构造函数循环依赖(无法解决)

首先要解决循环依赖就是要先实例化,然后放入三级缓存暴露出来,那么如果是构造函数这一步循环依赖, 实例化的时候就会产生无限递归创建,所以不能别解决 如果是延迟加载的话可以解决(另当别论)

②setter方式的多例的循环依赖(无法解决):

如果是多例的,在容器初始化的时候,不会去创建,所以早期没有放入到三级缓存中暴露出来,所以无法解 决循环依赖,会报错

③setter方式的单例循环依赖(A依赖B,B依赖A):

A与B循环依赖,都要被代理的情况 1.A实例化->A放入三级缓存->依赖注入B->B实例化->B放入三级缓存->依赖注入a->去三级缓存拿a的代理 ->把代理的A放入二级->返回a的代理注入到B->b初始化->走后置通知获得代理b->B的代理放入一级缓存、 ->原生a依赖注入b->A初始化->后置通知,不走代理返回原生A->再偷天换日->放入一级缓存

11、说说对spring AOP的理解和使用?

分析:考察对spring理解和使用,可以围绕 aop的概念、实现方式、springAop支持的方式回答

答:aop是一种面向切面编程的思想,是对oop思想的补充,是将多个类处理业务逻辑的公共部分抽离出来,达到现复用、简化代码、解耦的目的。主要通过动态生成其代理对象来实现,常见的主流技术有JDK和CGLIB。

spring的AOP是基于JDK和CGLIB两种动态代理技术作为支撑的,默认为JDK代理,可以收到配置强制使用CGLIB,如果代理类没有实现接口也会采用CGLIB进行代理,Spring AOP典型使用为事务、通知等,同时我们也可以用来做请求日志记录、鉴权等操作

12、说下springmvc的流程

分析:考察springmvc的理解,需要平时注意、积累经验

答:

  • 用户发送请求至前端控制器DispatcherServlet
  • DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler
  • 处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返 回给
    DispatcherServlet;
  • DispatcherServlet 调用 HandlerAdapter处理器适配器(就是为了匹配参数),请求执行Handler;
  • HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑(controller);
  • Handler执行完成返回ModelAndView;
  • HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
  • DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
  • ViewResolver解析后返回具体View;
  • DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
  • DispatcherServlet响应用户

在这里插入图片描述

13、Spring如何保证线程安全的?

分析:考察对spring整体理解,以及线程安全方面的综合知识,spring是没有解决线程安全的,可以从bean的作用域回答

答:首先spring并未帮我们解决线程安全的问题,在spring中bean的作用域分别为 单例、多例、request、session级别、容器级别goal-session,其中只有多例是线程安全的,其他都会有线程安全问题,因此如果要解决安全问题,可以将bean设置成多例模式,另外基于bean的创建特性,我们的bean如果是无状态bean也不会有安全问题,因此我们在设置bean的时候尽量不要给bean动态赋值,保证bean为无状态bean,另外还可以给bean赋值或者操作值时加锁,不过性能比较低。

14、Spring事务和Mysql事务有什么区别?

分析:这种就是面试官挖坑,看你是否真正理解spring 事务本质

答:spring是没有事务的事务是由数据库本身决定的,spring只是管理事务,如果数据库本身不支持,那spring也不会生效

15、spring的事务失效场景

分析:spring事务是基于aop实现的,所以让aop失效的都会导致事务失效,另外还和数据库本身有关

:1.public方法 会导致事务失效,因为不能进行JDK或者CGLIB代理

2.调用本类的方法 (调用this.methodC方法),通过this调用不会走代理类

3.抛出捕捉的非RuntimeException,如果想要捕捉所有异常(rollbackFor = {Exception.class}) 
或者指定@Transactional(rollbackFor = {RuntimeException.class,ClassNotFoundException.class},
propagation = Propagation.REQUIRED) 多个异常类

4.事务隔离级别设置成 不支持事务

5.数据库不支持事务

16、说说你对spring事务的理解?

分析:从事务的隔离级别、传播机制、spring事务三个方面作答

答:首先spring是没有事务的,事务是由数据库本身决定的,spring的事务开启方式有两种,一个是声明式事务,一个是编程式事务,声明式事务是通过添加Transaction注解 的方式开启事务,使用spring aop实现,一般加在类或者方法上,事务控制粒度比较大,但使用上比较方便,编程式事务通过 TransactionTemplate,控制事务的粒度小,但是代码侵入性比较强。

spring事务提供了7中传播机制:

  • Required 需要 如果存在一个事务,则支持当前事务。如果没有事务则开启
  • Supports 支持 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
  • Mandatory 必要的 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
  • required_new 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
  • Not_support 总是非事务地执行,并挂起任何存在的事务。
  • Never 绝不 总是非事务地执行,如果存在一个活动事务,则抛出异常
  • Nested 嵌套的 如果有就嵌套、没有就开启事务

spring事务还提供了四种隔离级别:

1. DEFAULT(-1):数据库默认的隔离级别

2. READ_UNCOMMITTED(1):读未提交 ru,会导致脏读

3. READ_COMMITTED(2):读已提交 rc 避免脏读,允许不可重复读和幻读

4. REPEATABLE_READ(4):可重复读 rr 避免脏读,不可重复读,允许幻读,innodb存储引擎解决了幻读

5. SERIALIZABLE:串行化(不会使用这种)

17. Spring事务是怎么实现的?

  1. Spring事务底层是基于数据库事务AOP机制
  2. 首先对于使用了@Transactional注解的Bean,Spring会创建一个代理对象作为Bean
  3. 当调用代理对象的方法时,会先判断该方法上是否加了@Transactional注解
  4. 如果加了,那么则利用事务管理器创建一个数据库连接
  5. 并且修改数据库连接的autocommit属性为false禁止此连接的自动提交,这是实现Spring事务非常重要的一步
  6. 然后执行当前方法,方法中会执行sql
  7. 执行完当前方法后,如果没有出现异常就直接提交事务
  8. 如果出现了异常,并且这个异常是需要回滚的就会回滚事务,否则仍然提交事务

注:

  1. Spring事务的隔离级别对应的就是数据库的隔离级别
  2. Spring事务的传播机制是Spring事务自己实现的,也是Spring事务中最复杂的
  3. Spring事务的传播机制是基于数据库连接来做的,一个数据库连接就是一个事务,如果传播机制配置为需要新开一个事务,那么实际上就是先新建一个数据库连接,在此新数据库连接上执行sql
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在知乎中,关于2022Spring面试题的讨论有很多。Spring是一个非常流行的Java企业级开发框架,相关面试题主要围绕该框架的核心概念、特性以及应用进行。 首先,一些常见的Spring面试题可能涉及到IoC(控制反转)和DI(依赖注入)的概念和原理。回答此类问题时,我们可以解释IoC是一种设计模式,通过将对象的创建和管理交给Spring容器来实现,这样可以提高代码的可维护性和扩展性。而DI是IoC的一种具体实现方式,通过依赖注入来实现对象之间的解耦。 其次,关于Spring的AOP(面向切面编程)也是一个常见的面试题。我们可以解释AOP是一种通过将横切关注点(例如日志记录、性能监控等)与主要业务逻辑进行解耦的编程思想。Spring提供了一种基于代理模式的AOP实现方式,可以通过切面、连接点、切点和通知等概念来实现对关注点的管理和处理。 此外,关于Spring MVC的问题也常常出现在面试中。我们可以解释Spring MVC是Spring框架中用于开发Web应用的模块,它采用了基于MVC设计模式的思想,通过DispatcherServlet、HandlerMapping、Controller、ViewResolver等组件来实现请求的处理和响应的生成。 另外,对于Spring中的常用注解(例如@Controller、@Service、@Autowired等)的理解,以及它们在项目中的应用也是一个常见的面试题。我们可以解释这些注解的作用和使用方式,说明它们可以简化开发流程、提高代码的可读性和可维护性。 总结来说,回答Spring面试题主要需要对Spring框架的核心原理、概念和应用有一定的理解,并能够将其与具体的项目场景进行结合,以展示个人的实际应用能力和经验。同时,在准备面试时,也可以通过查阅相关书籍、官方文档和参与实际开发来巩固和扩展自己的知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值