JavaWeb编程面试题——Spring Framework

引言

面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待。不以刷题进大厂为目的,而是以学习为目的。这里的知识点会持续更新,目录也会随时进行调整。

关注公众号:编程火箭车。在【粉丝福利】中点击【面题大全】,其中的Java面试题在线实时更新、查看。


一、面试题导航

点这里进入JavaWeb编程面试题——导航

面试题持续更新中......

二、面试题目

1.什么是Spring框架?Spring框架有哪些主要模块?

Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性。
一般说 Spring 框架指的是 Spring Framework,它是很多模块的集合,这些模块是:核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。Spring 框架的主要目的是简化 Java 后端开发工作。

2.Spring的优点?

  • Spring 属于低侵入式设计,代码的污染极低;

  • Spring 的 DI 机制将对象之间的依赖关系交由框架处理,降低组件的耦合度;

  • Spring 提供了 AOP 技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用;

  • Spring 对于主流的应用框架提供了集成支持。

3.列举一些重要的Spring模块?

image

一些重要的 Spring Framework 模块:

  • Spring Core:基础,可以说 Spring 其他所有的功能都需要依赖于该核心库。主要提供 IOC 依赖注入功能。

  • Spring AOP:提供了面向切面的编程实现。

  • Spring Aspects:该模块为与 AspectJ 的集成提供支持。

  • Spring JDBC:Java 数据库连接。

  • Spring JMS:Java 消息服务。

  • Spring ORM:用于支持 Mybatis、Hibernate 等 ORM 框架的支持。

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

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

4.谈谈对Spring IoC的理解?

IoC(Inverse of Control:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权交由 Spring 框架来管理。IoC 在其他语言中也有应用,并非 Spring 特有。IoC 容器是 Spring 用来实现 IoC 的载体,IoC 容器实际上就是个 Map(key, value),Map 中存放的是各种对象。
将对象之间的相互依赖关系交给 IOC 容器来管理,并由 IOC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC 容器就像一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件或注解即可,完全不用考虑对象是如何被创建出来的。

5.DI是什么?

IOC 的一个重点就是在程序运行时,动态的向某个对象提供它所需要的其他对象,这一点是通过 DI(Dependency Injection,依赖注入)来实现的,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖。而 Spring 的 DI 具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。

6.IOC与DI有什么区别?

IOC 是解决耦合问题的一种设计思想,DI 是 IOC 的一种实现。IOC 主要的实现方式有两种:依赖查找(DL),依赖注入(DI)。

7.谈谈对Spring AOP的理解?

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无法,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

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

使用 AOP 之后我们可以把一些通用的功能抽象出来,在需要用到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,提供了系统的扩展性。日志功能、事务管理等等场景都用到了 AOP。

8.静态代理与动态代理有什么区别?

AOP 实现的关键在于 代理模式,AOP 代理主要分为静态代理和动态代理。静态代理的代表为 AspectJ;动态代理则以 Spring AOP 为代表。静态代理与动态代理区别在于生成 AOP 代理对象的时机不同

(1)AspectJ 是静态代理,也称为编译时增强,AOP 框架会在编译阶段生成 AOP 代理类,并将 AspectJ(切面)织入到 Java 字节码中,运行的时候就是增强之后的 AOP 对象。

(2)Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

9.JDK动态代理和CGLIB动态代理的区别?

(1)JDK 动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类,在获取代理对象时,使用 Proxy 类来动态创建目标类的代理类(即最终真正的代理类,这个类继承自 Proxy 并实现了我们定义的接口),当代理对象调用真实对象的方法时, InvocationHandler 通过 invoke() 方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;

(2)如果被代理类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现 AOP。CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。

10.Spring支持几种Bean的作用域?

当通过 Spring 容器创建一个 Bean 实例时,不仅可以完成 Bean 实例的实例化,还可以为 Bean 指定特定的作用域。

Spring 支持如下6种作用域:

  • singleton:单例模式,在整个 Spring IoC 容器中,使用 singleton 定义的 Bean 将只有一个实例。

  • prototype:原型模式,每次通过容器的 getBean 方法获取 prototype 定义的 Bean 时,都将产生一个新的 Bean 实例。

  • request:对于每次 HTTP 请求,使用 request 定义的 Bean 都将产生一个新实例,即每次 HTTP 请求将会产生不同的 Bean 实例。只有在 Web 应用中使用 Spring 时,该作用域才有效。

  • session:对于每次 HTTP Session,使用 session 定义的 Bean 都将产生一个新实例。同样只有在 Web 应用中使用 Spring 时,该作用域才有效。

  • application:整个应用活动期间。

  • websocket:一次端口通信。

其中比较常用的是 singleton 和 prototype 两种作用域。对于 singleton 作用域的 Bean,每次请求该 Bean 都将获得相同的实例。容器负责跟踪 Bean 实例的状态,负责维护 Bean 实例的生命周期行为;如果一个 Bean 被设置成 prototype 作用域,程序每次请求该 id 的 Bean,Spring 都会新建一个 Bean实例,然后返回给程序。在这种情况下,Spring 容器仅仅使用 new 关键字创建 Bean 实例,一旦创建成功,容器不在跟踪实例,也不会维护 Bean 实例的状态。

如果不指定 Bean 的作用域,Spring 默认使用 singleton 作用域。Java 在创建 Java 实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype 作用域 Bean 的创建、销毁代价比较大。而 singleton 作用域的 Bean 实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将 Bean 被设置成 prototype 作用域。

11.Spring常用的注入方式有哪些?

Spring 通过 DI(依赖注入)实现 IOC(控制反转),常用的注入方式主要有三种:

  • 构造方法注入

  • Setter 注入

  • 基于注解的注入

12.Spring自动装配Bean有哪些方式?

Spring 容器负责创建应用程序中的 Bean 同时通过 ID 来协调这些对象之间的关系。作为开发人员,我们需要告诉 Spring 要创建哪些 Bean 并且如何将其装配到一起。

Spring 中 Bean 装配有两种方式:

  • 隐式的 Bean 发现机制和自动装配

  • 在 Java 代码或者 XML 中进行显示配置

当然这些方式也可以配合使用。

13.Spring中的Bean是线程安全的吗?

Spring 中的 Bean 默认是单例模式,Spring 容器本身并没有提供线程安全的策略,因为是否线程安全完全取决于 Bean 本身的特性。但是具体情况还是要结合 Bean 的作用域来讨论。

  • 对于 prototype 作用域的 Bean,每次都创建一个新对象,也就是线程之间不存在 Bean 共享,因此不会有线程安全问题。

  • 对于 singleton 作用域的 Bean,所有的线程都共享一个单例实例的 Bean,因此是存在线程安全问题的。但是如果单例 Bean 是一个无状态 Bean,也就是线程中的操作不会对 Bean 的成员执行查询以外的操作,那么这个单例 Bean 是线程安全的。比如 Controller 类、Service 类和 Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。

有状态 Bean(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。
无状态 Bean(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。

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

关于下面一些设计模式的详细介绍

  • 工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 Bean 对象。

  • 代理设计模式 : Spring AOP 功能的实现。

  • 单例设计模式 : Spring 中的 Bean 默认都是单例的。

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

  • 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。

  • 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。

  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配 Controller。

15.@Component和@Bean的区别是什么?

(1)作用对象不同: @Component 注解作用于类,而 @Bean 注解作用于方法。

(2)@Component 通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 Bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 Bean,@Bean 告诉了 Spring 这是某个类的示例,当我需要用它的时候还给我。

(3)@Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册Bean。比如当我们引用第三方库中的类需要装配到 Spring 容器时,则只能通过 @Bean 来实现。

16.将一个类声明为Spring的Bean的注解有哪些?

我们一般使用 @Autowired 注解自动装配 Bean,要想把类标识成可用于 @Autowired 注解自动装配的 Bean 的类,采用以下注解可实现:

  • @Component :通用的注解,可标注任意类为 Spring 组件。如果一个Bean不知道属于拿个层,可以使用 @Component 注解标注。

  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。

  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。

  • @Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。

17.Spring事务实现方式有哪些?

编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用 beginTransaction()、commit()、rollback() 等事务管理相关的方法,这就是编程式事务管理。

  • 基于 TransactionProxyFactoryBean 的声明式事务管理。

  • 基于 @Transactional 的声明式事务管理。

  • 基于 Aspectj AOP 配置事务。

18.Spring中一个接口有多个实现类如何不同注入我所需要的类?

  • @Autowired 是通过 byType 的方式去注入的,使用该注解,要求接口只能有一个实现类。

  • @Resource 可以通过 byName 和 byType 的方式注入,默认先按 byName 的方式进行匹配,如果匹配不到,再按 byType 的方式进行匹配。

  • @Qualifier 注解可以按名称注入,但是注意是类名。

19.为什么要使用Spring?

(1)简介

  • 目的:解决企业应用开发的复杂性;

  • 功能:使用基本的 JavaBean 代替 EJB,并提供了更多的企业应用功能;

  • 范围:任何 Java 应用;

  • 简单来说,Spring 是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

(2)轻量

从大小与开销两方面而言 Spring 都是轻量的。并且 Spring 所需的处理开销也是微不足道的。此外,Spring 是非侵入式的:典型地,Spring 应用中的对象不依赖于 Spring 的特定类。

(3)控制反转

Spring 通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了 IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为 IoC 与 JNDI 相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

(4)面向切面

Spring 提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

(5)容器

Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个 Bean 如何被创建——基于一个可配置原型(prototype),你的 Bean 可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring 不应该被混同于传统的重量级的 EJB 容器,它们经常是庞大与笨重的,难以使用。

(6)框架

Spring 可以将简单的组件配置、组合成为复杂的应用。在 Spring 中,应用对象被声明式地组合,典型地是在一个 XML 文件里。Spring 也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

所有 Spring 的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为 Spring 中的各种模块提供了基础支持。

20.@Autowired和@Resource之间的区别?

  • @Autowired 默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它 required 属性为 false)。

  • @Resource 默认是按照名称来装配注入的,只有当找不到与名称匹配的 Bean 才会按照类型来装配注入。


关注公众号:编程火箭车
我们定期发布编程相关的文章、资讯、活动等内容。帮助编程爱好者、初学者或初级程序员快速入门、打牢基础。欢迎大家关注,和我们一起探索编程的精彩世界。

posted @ 2023-05-25 08:17  编程火箭车  阅读(813)  评论(0编辑  收藏  举报