Spring 面试题

Spring 面试题

Spring 家族

  • Spring Core:
    • Spring MVC:工厂模式和代理模式,用于解耦应用组件
    • Spring Boot:模板代码
    • Spring Clound:微服务

Spring IOC

IOC 就是 Inversion of Control,控制反转。先了解依赖注入(Dependency Injection)。

在以前的开发中,上层建筑依赖于下层建筑。每个类都调用成员的构造函数,都是直接 new 出来的。


这时,如果我们想修改 Tire 类,支持动态设置 size,那么就要修改所有的类。


如果我们每次修改一个类,都要修改所有依赖它的类,可维护性就非常差。

依赖注入就可以解耦,把底层类作为参数传递给上层类,实现上层对下层的控制


这种做法还有利于单元测试和协同开发。

而 IOC 就是通过 DI 实现的(DL 已经被抛弃,因为具有侵入性)。


依赖注入的方式:

  • Setter
  • Interface:实现特定的接口,供 IOC 容器注入所依赖类型的对象(废弃)
  • Constructor:实现特定参数的构造函数
  • Annotation:如 AutoWierd


- 依赖倒置原则是思想 - 控制反转是思路 - 依赖注入是具体的实现方法 - IOC 容器也是一种实现方法,统一管理 Bean 的生命周期

IOC 容器的优势

  • 避免在各处使用 new 来创建类,并且可以并做到统一维护
  • 在创建实例时,不需要了解其中的细节,就像是一个工厂,会根据依赖关系去创建对象,隐藏了细节。增加了可维护性,降低开发难度


Spring IOC 流程

  • 从配置文件或者注解,读取配置信息,配置 Bean 注册表
  • 根据 Bean 注册表,利用反射实例化 Bean,建立 Bean 之间的依赖关系
  • 将 Bean 实例放到 Spring 容器中


Spring IOC 支持的功能

  • 依赖注入
  • 依赖检查
  • 自动装配
  • 支持集合
  • 指定初始化和销毁方法
  • 支持回调方法(需要实现某些接口)

BeanFactory 与 ApplicationContext 的比较

  • BeanFactory 是 Spring 框架的基础设施,面向 Spring
  • ApplicationContext 面向使用 Spring 框架的开发者

getBean 方法的代码逻辑

  • 转换 beanName
  • 从缓存中加载实例
  • 实例化 Bean
  • 检测 parentBeanFactory
  • 初始化依赖的 Bean
  • 创建 Bean

Spring Bean 的作用域

  • singleton:Spring 的默认作用域,容器里拥有唯一的 Bean 实例,适合无状态的 Bean
  • prototype:针对每个 getBean 请求,容器都会创建一个 Bean 实例,适合有状态的 Bean,不过频繁创建和销毁 Bean 是有开销的
  • Web 容器里面,还有 3 种作用域
    • request:会为每个 Http 请求创建一个 Bean 实例
    • session:会为每个 session 创建一个 Bean 实例
    • globalSession:会为每个全局 Http Session 创建一个 Bean 实例,该作用域仅对 PorletContext 有效

Spring AOP

关注点分离:不同的问题交给不同的部分去解决

  • 通用化代码的实现(事务、缓存、日志)等,对应的就是切面
  • 业务代码和切面代码分开后,架构将变得高内聚、低耦合
  • 分开后,又需要合并到一起,切面最终需要被合并到业务中

AOP 的三种织入方式

  • 编译时织入:在编译时,融合进来,生成完整功能的字节码,需要特定编译器,如 AspectJ
  • 类加载时织入:在类加载时融合进来,需要特定编译器,如 AspectJ
  • 运行时织入:Spring 采用的方式,通过动态代理的方式,实现简单。会有性能上的开销,好处是不需要特定的编译器和类加载器。

AOP 的实现有 JDKProxy(动态代理)Cglib

  • 由 AopProxyFactory 根据 AdvicedSupport 对象的配置来决定

  • 默认策略:如果目标类是接口,则使用 JDKProxy 来实现,否则使用后者

  • JDKProxy 要求被代理的类必须实现一个接口,核心是 InvocationHandler 接口和 Proxy 类,通过 Java 内部的反射机制实现。反射机制在生成类的过程中比较高效

  • Cglib:是一个代码生成库,可以在运行时动态地生成某个类的子类,以继承的方式动态生成目标类的代理(final 类无法使用 Cglib),借助 ASM 实现。ASM 在生成类之后的执行过程中比较高效

Spring 里代理模式的实现

  • 真实实现类的逻辑包含在 getBean 方法里
  • getBean 方法返回的实际上是代理类的实例
  • 代理类的实例是 Spring 采用 JDK Proxy 或者 Cglib 动态生成的

评论