面试集中营—Spring篇

Spring 框架的好处

1、轻量:spring是轻量的,基本的版本大约2MB;

2、IOC:控制反转,Spring的IOC机制使得对象之间的依赖不再需要我们自己来控制了,而是由容易来控制,一个字:爽;

3、AOP:切面编程,Spring提供的AOP技术可以把应用逻辑和系统服务分来,编码更灵活,更方便;

4、MVC框架:如果使用过Struts2的同学,使用springmvc就会觉得非常的舒适,spring提供的mvc框架是一个非常优秀的Web框架;

5、全局事务管理:Spring提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务;

6、统一异常处理:

Autowired 和 Resource 注解的区别

共同点:都是做bean注入时使用的,都可以写在字段或者setter方法上面;

不同点:

1、包归属不同,@Autowired是Spring提供的注解,@Resource是javax提供的注解;

2、寻找bean的方式不同,@Resource默认是优先根据名称查找bean,而@Autowired默认是优先根据类型查找bean

SpringMVC的运行机制

这个问题已经很古老的,很多面试官也不会问,因为大家的侧重点都是在分布式高并发还有场景问题上。SpringMVC的处理请求过程或者说运行机制吧,大家可以通过设计模式的方式来去学习。

MVC模式

MVC分别代表了Model、View、Controller三个处理节点

C:控制器层,用于接受请求,调用业务类,最后派发页面;

M:数据模型层(包含service、dao、entity)主要是处理业务数据并返回处理结果;

V:视图渲染层,主要为了渲染页面。

在当前前后端分离已经成为了一个常态的情况下,V已经逐渐淡化了,但是在5年前前后端分离还没有那么的成熟,如果回到2016年,当时主流前端线下课都还没有vue2的课程存在,就是三大框架+jquery;那么mvc这个模式就是老子天下第一;

工作原理

springmvc主要通过中央处理器(DispatcherServlet)来统一调度。如下图所示

Bean的生命周期

经典的问题。提到生命周期,我们应该想到的是spring能够IOC其实就是保存了一个bean的实例池,所以生命周期的前期一定是实例化和初始化,实例化就是把对象在内存空间中分配出来,初始化就是给对象的属性赋值。当一个bean完成了使命后就要面临销毁,就会有一个销毁的过程。

只不过为了方便扩展,spring把实例化和初始化的过程进行了多重封装,方便开发者去介入bean的实例化过程。具体如下:

1、实例化 Bean :

对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 bean 时,或初始化 bean 的时候需要 注 入 另 一 个 尚 未 初 始 化 的 依 赖 时 , 容 器 就 会 调 用 createBean 进 行 实 例 化 。 对于 ApplicationContext容器,当容器启动结束后,通过获取 BeanDefinition 对象中的信息,实例 化所有的 bean。

2、设置对象属性(依赖注入):
实例化后的对象被封装在 BeanWrapper 对象中,紧接着, Spring 根据 BeanDefinition 中的信
息以及通过 BeanWrapper 提供的设置属性的接口完成依赖注入。
3、处理 Aware 接口:

接着,Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入 Bean :

  • 如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值;
  • 如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory()方法,传递的是 Spring 工厂自身。
  • 如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用setApplicationContext (ApplicationContext)方法,传入Spring上下文;

4、BeanPostProcessor:

如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,那将会调用 postProcessBeforeInitialization(Object obj, Strings)方法。

5、InitializingBean 与 init-method :

如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法

6、 如果这个Bean实现了BeanPostProcessor 接口,将会调用postProcessAfterInitialization (Object obj, Strings)方法;由于这个方法是在 Bean 初始化结束时调用的,所以可以被应用于内存或缓存技术;

7、DisposableBean

当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现 的 destroy()方法;

8、destroy-method

最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销 毁方法。

spring框架中都用到了哪些设计模式

1、简单工厂模式:Spring 中的 BeanFactory 就是简单工厂模式的体现。根据传入一个唯一的标识来获得Bean 对象,但是在传入参数后创建还是传入参数前创建,要根据具体情况来定。
2、工厂模式 : Spring 中的 FactoryBean 就是典型的工厂方法模式,实现了 FactoryBean 接口的
bean 是一类叫做 factory 的 bean 。其特点是, spring 在使用 getBean() 调用获得该 bean 时,
会自动调 用该 bean 的 getObject() 方法,所以返回的不是 factory 这个 bean ,而是这个
bean.getOjbect() 方法的返回值。
3、单例模式 :在 spring 中用到的单例模式有:scope="singleton" ,注册式单例模式, bean 存放
于 Map 中。 bean name 当做 key , bean 当做 value 。
4、原型模式 :在 spring 中用到的原型模式有:scope="prototype" ,每次获取的是通过克隆生成的新实例,对其进行修改时对原有实例对象不造成任何影响。
5、代理模式 : Spring 中经典的 AOP ,就是使用动态代理实现的,分 JDK 和 CGlib 动态代理。
6、适配器模式 : Spring 中的 AOP 中 AdvisorAdapter 类,它有三个实现:
MethodBeforAdviceAdapter 、 AfterReturnningAdviceAdapter 、 ThrowsAdviceAdapter 。 Spring
会根据不同的 AOP 配置来使用对应的 Advice ,与策略模式不同的是,一个方法可以同时拥有多
个 Advice。 Spring 存在很多以 Adapter 结尾的,大多数都是适配器模式。
7、观察者模式 : Spring 中的 Event 和 Listener 。 spring 事件: ApplicationEvent ,该抽象类继
承了 EventObject 类, JDK 建议所有的事件都应该继承自 EventObject 。 spring 事件监听器:
ApplicationListener ,该接口继承了 EventListener 接口, JDK 建议所有的事件监听器都应该
继承 EventListener 。
8、模板模式 : Spring 中的 org.springframework.jdbc.core.JdbcTemplate 就是非常经典的模板模
式的应用,里面的 execute 方法,把整个算法步骤都定义好了。

Spring是怎么解决循环依赖的?

一句话就是spring是通过三级缓存来解决循环依赖的,所以如果有人问spring的三级缓存是干什么的,也是一样的,是解决循环依赖问题的。具体来说,就是A依赖B,B依赖C,C又依赖了A,产生了循环。spring在实例化Bean的过程中,当发现有一个属性是对象,就会尝试去获取这个对象的bean,递归调用又调用回来了,发现自身还在创建中,那么说明发生了循环依赖。解决流程如下:

1、A先初始化第一步提前把自己暴露出来,(通过一个对象工厂的方式存在三级缓存中),

当发现依赖对象B时,就尝试获取B的bean;

2、B没有创建,走创建流程,发现自己依赖的C也没有创建;

3、C走创建流程,发现依赖A,此时A在三级缓存中,通过 ObjectFactory#getObject() 方法来拿到 A 对象,此时C顺利完成初始化,并将自己添加到一级缓存中;

4、B拿到了C的bean,也完成了初始化,将自己添加到一级缓存中;

5、A又拿到了B的bean,完成了初始化,将自己添加到一级缓存中;

Spring事务传播级别

Spring 事务定义了 7 种传播机制:

  1. PROPAGATION_REQUIRED:默认的 Spring 事务传播级别,若当前存在事务,则加入该事务,若不存在事务,则新建一个事务。

  2. PAOPAGATION_REQUIRE_NEW:若当前没有事务,则新建一个事务。若当前存在事务,则新建一个事务,新老事务相互独立。外部事务抛出异常回滚不会影响内部事务的正常提交。

  3. PROPAGATION_NESTED:如果当前存在事务,则嵌套在当前事务中执行。如果当前没有事务,则新建一个事务,类似于 REQUIRE_NEW。

  4. PROPAGATION_SUPPORTS:支持当前事务,若当前不存在事务,以非事务的方式执行。

  5. PROPAGATION_NOT_SUPPORTED:以非事务的方式执行,若当前存在事务,则把当前事务挂起。

  6. PROPAGATION_MANDATORY:强制事务执行,若当前不存在事务,则抛出异常.

  7. PROPAGATION_NEVER:以非事务的方式执行,如果当前存在事务,则抛出异常。

相关推荐
邵泽明38 分钟前
面试知识储备-多线程
java·面试·职场和发展
戊子仲秋1 小时前
【LeetCode】每日一题 2024_10_2 准时到达的列车最小时速(二分答案)
算法·leetcode·职场和发展
夜流冰2 小时前
工具方法 - 面试中回答问题的技巧
面试·职场和发展
penguin_bark3 小时前
LCR 068. 搜索插入位置
算法·leetcode·职场和发展
杰哥在此9 小时前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
GISer_Jing15 小时前
【React】增量传输与渲染
前端·javascript·面试
Neituijunsir20 小时前
2024.09.22 校招 实习 内推 面经
大数据·人工智能·算法·面试·自动驾驶·汽车·求职招聘
希望有朝一日能如愿以偿20 小时前
力扣题解(飞机座位分配概率)
算法·leetcode·职场和发展
小飞猪Jay21 小时前
面试速通宝典——10
linux·服务器·c++·面试
猿java1 天前
Cookie和Session的区别
java·后端·面试