Spring 面经

1 什么是 Spring?

Spring 是一个轻量级的 IoC 和 AOP 容器框架。是为 Java 应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于 XML 的配置、基于注解的配置、基于 Java 的配置。

2 Spring 的优点?

  1. Spring 属于低侵入式设计,代码的污染极低
  2. Spring 的 DI 机制将对象之间的依赖关系交由框架处理,减低组件的耦合性
  3. Spring 提供了 AOP 技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用
  4. Spring 对于主流的应用框架提供了集成支持

3 如何理解 Spring 中的 IoC ?

IOC 就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到 Spring 容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。

最直观的表达就是,IOC 让对象的创建不用去 new 了,可以由 Spring 自动生产,使用 java 的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。

Spring 的 IOC 有三种注入方式 :构造器注入,setter 方法注入,根据注解注入。

4 如何理解 DI ?

DI,即依赖注入,和控制反转是同一个概念的不同角度的描述,即应用程序在运行时依赖 IoC 容器来动态注入对象需要的外部资源。

5 如何理解 Spring 中的 AOP ?

在介绍 AOP 之前,我们先来了解一下 OOP 的概念。OOP 又指面向对象,它允许开发者定义纵向的关系,但并不适用于定义横向的关系,导致了大量代码的重复,而不利于各个模块的重用。

AOP,又被称为面向切面,它是作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为切面(Aspect)。

AOP 减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。

AOP 实现的关键在于代理模式,AOP 代理主要分为静态代理和动态代理。静态代理的代表为AspectJ,而动态代理则以 Spring AOP 为代表。

6 AspectJ 与 Spring AOP 的区别?

  1. AspectJ 是静态代理的增强,所谓静态代理,就是 AOP 框架会在编译阶段生成 AOP 代理类,因此也称为编译时增强,它会在编译阶段将切面织入到 Java 字节码中,运行的时候就是增强之后的 AOP 对象。
  2. Spring AOP 使用的是动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。(Spring AOP 中的动态代理主要有两种方式, JDK 动态代理和 CGLIB 动态代理)

7 请介绍一下 BeanFactory 和 ApplicationContext ?

BeanFactory 和 ApplicationContext 是 Spring 的两大核心接口,都可以当做 Spring 的容器。其中 ApplicationContext 是 BeanFactory 的子接口。

BeanFactory 是 Spring 里面最底层的接口,包含了各种 bean 的定义,读取 bean 配置文档,管理 bean 的加载、实例化,控制 bean 的生命周期,维护 bean 之间的依赖关系。

ApplicationContext 接口作为 BeanFactory 的派生,除了提供 BeanFactory 所具有的功能外,还提供了更完整的框架功能,例如支持国际化,提供统一的资源文件访问方式,提供在监听器中注册 bean 的事件,允许同时加载多个配置文件,载入多个(有继承关系)上下文(使得每一个上下文都专注于一个特定的层次,比如应用的 web 层)等等。

8 BeanFactory 和 ApplicationContext 有哪些区别?

  1. BeanFactroy 采用延迟加载的形式来注入 Bean 的,即只有在使用到某个 Bean 时,才对该 Bean 进行加载实例化。而 ApplicationContext 会在容器启动时,一次性创建了所有的 Bean
  2. BeanFactory 通常以编程的方式被创建,而 ApplicationContext 还能以声明的方式创建,如使用 ContextLoader
  3. BeanFactory 和 ApplicationContext 都支持 BeanPostProcessor、BeanFactoryPostProcessor 的使用,但两者之间的区别是:BeanFactory 需要手动注册,而 ApplicationContext 则是自动注册

9 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. InitializingBean 与 init-method:如果 Bean 在 Spring 配置文件中配置了 init-method
    属性,则会自动调用其配置的初始化方法
  5. BeanPostProcessor:该方法在 Bean 初始化结束时调用,如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现 BeanPostProcessor 接口。该步骤结束后,Bean 就已经被正确创建了
  6. DisposableBean:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy() 方法
  7. destroy-method:如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法

10 Spring 支持的几种 bean 的作用域?

  1. singleton:默认,每个容器中只有一个 bean 的实例,单例的模式由 BeanFactory 自身来维护
  2. prototype:为每一个 bean 请求提供一个实例
  3. request:为每一个网络请求创建一个实例,在请求完成以后,bean 会失效并被垃圾回收器回收
  4. session:与 request 范围类似,确保每个 session 中有一个 bean 的实例,在 session 过期后,bean 会随之失效
  5. global-session:全局作用域

11 Spring 中的单例 Bean 是线程安全的吗?

Spring 框架并没有对单例 bean 进行任何多线程的封装处理,需要开发者自行处理。如果 Spring bean 并没有可变的状态,那么它是线性安全的。如果 bean 有多种状态,则需要自行保证线程安全,例如将其作用域从 singleton 改为 prototype。

12 Spring 如何处理线程并发问题?

在一般情况下,只有无状态的 Bean 才可以在多线程环境下共享,在 Spring 中,绝大部分 Bean 都可以声明为 singleton 作用域,因为 Spring 对一些 Bean 中非线程安全状态采用 ThreadLocal 进行处理,解决线程安全问题。

13 Spring 的自动装配?

在 Spring 中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使用 autowired 来配置自动装载模式。

在 Spring 框架 xml 配置中共有5种自动装配:

  1. no:默认的方式是不进行自动装配的,通过手工设置 ref 属性来进行装配 bean
  2. byName:通过 bean 的名称进行自动装配,如果一个 bean 的 property 与另一 bean 的 name 相同,就进行自动装配
  3. byType:通过参数的数据类型进行自动装配
  4. constructor:利用构造函数进行装配,并且构造函数的参数通过 byType 进行装配
  5. autodetect:自动探测,如果有构造方法,通过 construct 的方式自动装配,否则使用 byType 的方式自动装配

基于注解的方式:

使用 @Autowired 注解来自动装配指定的 bean。在使用 @Autowired 注解之前需要在 Spring 配置文件进行配置 <context:annotation-config />。

在启动 Spring IoC 时,容器自动装载了一个后置处理器,当容器扫描到 @Autowied、@Resource 或 @Inject 时,就会在 IoC 容器自动查找需要的 bean,并装配给该对象的属性。

在使用 @Autowired 时,首先在容器中查询对应类型的 bean:如果查询结果刚好为一个,就将该 bean 装配给 @Autowired 指定的数据;如果查询的结果不止一个,那么 @Autowired 会根据名称来查找;如果上述查找的结果为空,那么会抛出异常。解决方法时,使用 required=false。

14 @Autowired 和 @Resource 之间的区别?

  1. @Autowired 默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它 required 属性为 false)
  2. @Resource 默认是按照名称来装配注入的,只有当找不到与名称匹配的 bean 才会按照类型来装配注入。

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

  1. 工厂模式:BeanFactory 就是简单工厂模式的体现,用来创建对象的实例
  2. 单例模式:Bean 默认为单例模式
  3. 代理模式:Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术
  4. 模板方法:用来解决代码重复的问题,比如 RestTemplate
  5. 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring 中 listener 的实现 – ApplicationListener

16 Spring 事务的种类?它们之间的区别?

  1. 编程式事务:使用 TransactionTemplate
  2. 声明式事务:建立在 AOP 之上,其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过 @Transactional 注解的方式,便可以将事务规则应用到业务逻辑中。

声明式事务要优于编程式事务,这正是 Spring 倡导的非侵入式的开发方式,使业务代码不受污染,只要加上注解就可以获得完全的事务支持。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

17 Spring 包括哪几个模块?

  1. Spring Core:核心类库,提供 IOC 服务
  2. Spring Context:提供框架式的 Bean 访问方式,以及企业级功能(JNDI、定时任务等)
  3. Spring AOP:AOP 服务
  4. Spring DAO:对 JDBC 的抽象,简化了数据访问异常的处理
  5. Spring ORM:对现有的 ORM 框架的支持
  6. Spring Web:提供了基本的面向 Web 的综合特性,例如多方文件上传
  7. Spring MVC:提供面向 Web 应用的 Model-View-Controller 实现

参考:Spring常见面试题总结(超详细回答)

发布了127 篇原创文章 · 获赞 237 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Geffin/article/details/104101716