竹笋

首页 » 问答 » 常识 » 一面试题集之2022年spring高
TUhjnbcbe - 2023/2/24 8:40:00

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

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

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

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

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

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

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

SpringJDBC:Java数据库连接。

SpringJMS:Java消息服务。

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

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

SpringTest:提供了对JUnit和TestNG测试的支持。

Springtx:事务管理、

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

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

答:

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

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

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

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

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

分析:考察对springbean创建过程的掌握,出现关键词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

②注解配合:

Componet+

ComponentScan

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

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

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

6、说说bean的生命周期?

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

答:

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

1、因此实现了BeanFactoryPostProcessor接口的bean,在加载其他的bean的时候,也会调用这个bean的postProcessBeanFactory方法,可以在这个步骤去对bean中的属性去赋值,对所有bean生效的,适合多个bean都有相同属性值的对象使用

2、实现了InstantiationAwareBeanPostProcessor接口的bean,会在实例化bean之前调用postProcessBeforeInstantiation方法

3、通过反射创建bean,即实例化bean

4、对bean进行属性注入

5、对bean进行初始化操作:

实现了BeanFactoryAware接口,会先调用setBeanFactory方法

实现了BeanNameAware接口,会先调用setBeanName方法

实现了BeanPostProcessor接口,会先调用postProcessBeforeInitialization方法

实现了InitializingBean接口,会调用afterPropertiesSet方法

然后在进行aop后置处理,通过实现BeanPostProcessor接口,在postProcessAfterInitialization方法中进行动态代理

使用

销毁

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

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

答:

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

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

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

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

观察者设计模式:Spring事件驱动模型就是观察者模式很经典的应用。spring的事件流程:1)定义一个事件:实现一个继承自ApplicationEvent,并且写相应的构造函数2)定义一个事件监听者:实现ApplicationListener接口,重写onApplicationEvent()方法3)使用事件发布者发布消息:可以通过ApplicationEventPublisher的publishEvent()方法发布消息

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

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

适配器设计模式:适配器模式使得接口不兼容的那些类可以一起工作,其别名为包装器在SpringMVC中,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是如何解决循环依赖的?

答:

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、说说对springAOP的理解和使用?

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

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

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

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注解的方式开启事务,使用springaop实现,一般加在类或者方法上,事务控制粒度比较大,但使用上比较方便,编程式事务通过TransactionTemplate,控制事务的粒度小,但是代码侵入性比较强。

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

1.REQUIRED(必须的):是默认的传播机制,如果B方法中调用A,如果B中有事务,则A无论是否开启事务都会用B的事务,任何地方出现异常A和B都回滚

2.REQUIRES_NEW(需要新的):每次都会开启一个新的事务,外面事务回滚,里面事务不会回滚

3.SUPPORTS(1):如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行,完全依赖最外层事务

4.MANDATORY(强制性的):必须运行在事务里面

5.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

6.NEVER:以非事务方式执行,如果当前存在事务,则抛出异常7.NESTED:开启新事务,提交事务依赖于外层事务,如果外层事务回滚,则里面事务也回滚

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

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

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

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

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

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

OK~,本次spring高频面试题就分享到这里,点赞收藏,随时随地查看,祝同学们好运连连,面试必过

1
查看完整版本: 一面试题集之2022年spring高