每周10道Java面试题~第十期
- 1️⃣ 各个版本的Spring Framework有哪些主要功能?
- 2️⃣ 什么是Spring Framework?
- 3️⃣ Spring Framework有哪些优点?有哪些缺点?
- 4️⃣ Spring Framework中主要有哪些模块,分别提供什么功能?
- 5️⃣ 什么是Spring配置文件?
- 6️⃣ 详细讲一下Spring IOC及其实现原理?
- 7️⃣ 什么是Spring IOC容器?
- 8️⃣ 依赖注入(DI)是什么?有哪些方式完成依赖注入?优缺点是什么?
- 9️⃣ Spring Bean有哪几种作用域?有什么区别?
- 🔟 详细讲一下Spring AOP及其实现原理?
- 🎁 小山赠书活动
1️⃣ 各个版本的Spring Framework有哪些主要功能?
Spring Framework 历经2004年发布的 1.0版本到 2018年的 5.0版本,已经逐步发展成为一个功能强大、灵活多样的开发框架,被广泛应用于企业级Java应用程序的开发。
并且Spring Framework在2022年底还发布了 6.0新版本的相关消息,Spring Framework 6.0将继续推动Spring生态系统的发展,提供更加先进、灵活和高效的开发工具,以满足不断变化的业务需求和技术趋势。
下面是各个版本的Spring Framework的主要功能:
-
1.x 版本:主要提供了 IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)功能,并提供了对JDBC访问和事务管理的支持;
-
2.x 版本:在1.x版本的基础上,引入了注解支持、Java 5特性支持,增加了对Web应用程序的支持,包括MVC框架和Web服务的支持;
-
3.x 版本:支持 Java EE 6标准、RESTful风格的Web服务支持、Spring Expression Language(SpEL) 等新功能;
-
4.x 版本:增加了对Java 8新特性的支持,包括Lambda表达式和Stream API的支持等,提供Groovy语言支持、WebSocket支持 等新功能;
-
5.x 版本:引入了 响应式编程模型,提供了对 Reactive Streams和 WebFlux的支持,同时也支持Java 9和Java 10的新特性;
-
6.x 版本(即将发布):支持Java 17中的新特性和改进,采用模块化的架构将核心框架和各种扩展模块分离,支持更多的数据访问技术(例如NoSQL数据库、图形数据库等)等。
2️⃣ 什么是Spring Framework?
Spring Framework是一个开源的Java应用程序框架,最初由Rod Johnson在2003年创建。框架旨在通过丰富的特性和功能,帮助开发人员构建高效、灵活、可维护的应用程序。Spring框架提供了许多功能,包括依赖注入、AOP、JDBC集成、事务管理、Web应用程序开发等。
Spring框架的核心部分有:
-
IoC容器:Spring的IoC容器负责管理应用程序中的对象,并处理它们之间的依赖关系。开发人员只需定义对象和它们之间的关系,Spring容器就会自动创建和管理这些对象。这样可以将应用程序的逻辑与对象的创建和管理分离,提高了代码的可重用性和可维护性;
-
面向切面编程(AOP):通过AOP,可以将横切关注点(如日志记录、事务管理、安全性等)与业务逻辑分离,使得应用程序的代码更加简洁、可读性更高;
-
JDBC集成:Spring框架提供了JDBC模板,简化了JDBC编程,使得开发人员可以更加方便地访问和操作数据库;
-
事务管理:Spring框架提供了一种统一的事务管理机制,可以管理多个事务资源,如数据库连接、JMS队列等。开发人员可以通过声明式事务管理,将事务管理逻辑与业务逻辑分离;
-
Web应用程序开发:Spring框架提供了一个MVC框架,用于开发Web应用程序。MVC框架提供了控制器、视图、模型等组件,使得开发人员可以更加方便地开发Web应用程序。
除了以上主要特点外,Spring框架还提供了许多其他的功能,如集成测试、缓存、安全性、远程调用等。Spring框架的目标是提供高效、灵活、可重用的代码,使得Java开发人员可以更加方便地开发高质量的应用程序。
3️⃣ Spring Framework有哪些优点?有哪些缺点?
👉 作为一款优秀的开发框架,Spring Framework有以下优点:
- 简化开发工作:提供了丰富的功能和特性,可以简化开发人员的工作,让开发人员可以更加专注于业务逻辑的实现,而不用关注底层的技术细节;
- 提高代码质量:提供了一系列的最佳实践和设计模式,可以帮助开发人员编写高质量、可维护、可扩展的代码;
- 提高代码重用性:IoC容器和 AOP机制可以帮助开发人员实现组件的重用,使得代码更易于维护和扩展;
- 提高程序性能:JDBC模板、缓存、事务管理等功能可以帮助开发人员实现高效的数据访问和数据处理,提高应用程序的性能;
- 提高程序安全性:提供了一系列的安全性功能,如身份验证、访问控制、加密等,可以帮助开发人员实现应用程序的安全性;
- 支持集成测试:框架支持集成测试,可以帮助开发人员进行端到端的测试,保证应用程序的质量;
- 开放源代码:Spring框架是开放源代码的,开发人员不仅可以通过阅读源码学习和了解原理,还可以通过参与Spring社区,获取更多的技术支持和帮助。
📃 当然,凡事都有两面性,即便优秀如Spring Framework 也不例外,它也有以下几个缺点:
- 学习曲线较陡峭:Spring框架是一个庞大的框架,提供了丰富的功能和特性,学习起来需要花费一定的时间和精力;
- 运行效率较低:庞大体系结构和强大的功能特性会导致一定的性能损失。如果应用程序对性能要求比较高,可能需要进行优化;
- 配置较为复杂:Spring框架需要进行大量的配置,包括IoC容器的配置、AOP的配置、数据源的配置等。这些配置需要开发人员具备一定的技术水平,同时也会增加开发时间和成本;
- 依赖关系较为复杂:Spring框架的各个模块之间存在较为复杂的依赖关系,如果某个模块出现问题,可能会影响到其他模块的正常运行;
- 版本兼容:Spring框架的版本更新时,新版本可能会带来新的功能和特性,但也会导致一些旧版本的应用程序无法兼容。
4️⃣ Spring Framework中主要有哪些模块,分别提供什么功能?
Spring Framework主要包含以下模块:
- Spring Core模块:提供 IoC和 DI功能,包括 BeanFactory、ApplicationContext等;
- Spring AOP模块:提供 AOP功能,包括切面(Aspect)、连接点(Join Point)、通知(Advice)等。
- Spring Context 模块:向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能;
- Spring ORM模块:提供ORM(Object-Relational Mapping)功能,包括对Hibernate、JPA等的支持;
- Spring DAO模块:Spring 中的DAO提供一致的方式访问数据库,不管采用何种持久化技术,Spring都提供一致的编程模型。Spring还对不同的持久层技术提供一致的DAO方式的异常层次结构;
- Spring Web模块:提供Web开发相关的功能,包括Spring MVC、WebSocket等;
- Spring Web MVC 模块:Spring的MVC框架提供清晰的角色划分:控制器、验证器、命令对象、表单对象和模型对象、分发器、处理器映射和视图解析器。
这些模块为应用程序开发提供了广泛的支持,使得开发者可以快速地构建高质量、可维护的应用程序。
5️⃣ 什么是Spring配置文件?
Spring配置文件是指在Spring框架中用来配置应用程序组件的XML文件。
applicationContext.xml是Spring的默认配置文件,当容器启动时找不到指定的配置文档时,将会尝试加载这个默认的配置文件。
Spring配置文件通常存储在应用程序的classpath路径下,并由Spring框架在应用程序启动时加载。除了XML格式,Spring还支持其他格式的配置文件,如JavaConfig和GroovyConfig等。
它通常包含了Spring应用程序中各种对象的定义和它们之间的关系,例如 bean的定义、依赖注入、AOP配置、数据源配置等。Spring框架使用这些配置文件来实例化应用程序中的组件,并将它们装配在一起以构建完整的应用程序。
-
Bean定义:定义Spring中的各个组件和对象,包括数据源、事务管理器、服务层、DAO层等。可以通过配置文件中的bean标签进行定义和配置;
-
属性注入:配置Bean中的属性,包括基本类型、引用类型、集合类型等。可以通过配置文件中的property标签进行配置;
-
依赖注入:配置Bean之间的依赖关系,包括构造函数注入和setter方法注入两种方式。可以通过配置文件中的 constructor-arg和 property标签进行配置;
-
AOP配置:配置Spring框架中的AOP(面向切面编程)功能,包括切面、切点、通知等。可以通过配置文件中的aop命名空间进行配置;
-
MVC配置:配置Spring框架中的MVC(模型-视图-控制器)功能,包括控制器、视图解析器、视图渲染器等。可以通过配置文件中的mvc命名空间进行配置;
-
数据源配置:可以配置数据库连接池、数据库驱动、数据库用户名密码等信息。可以通过配置文件中的datasource标签进行配置;
-
事务配置:可以配置Spring框架中的事务管理器、事务注解等信息。可以通过配置文件中的tx命名空间进行配置。
Spring配置文件的编写需要遵循一定的规则和约定,可以通过Spring容器来读取和解析配置文件,并创建相应的Bean对象和组件。配置文件的正确性和合理性对于Spring应用程序的正常运行和性能表现至关重要。
🔍 关于spring的配置文件的更详细的各项配置的详情,可以参考这篇文章:
spring配置文件详解
6️⃣ 详细讲一下Spring IOC及其实现原理?
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心思想,它的实现手段是通过依赖注入(DI,Dependency Injection) 的方式来实现。
在传统的应用程序中,对象之间的依赖关系是由程序代码在对象内部通过new关键字等方式硬编码而成。而在Spring框架中,对象之间的依赖关系是由Spring容器在运行期间动态地通过反射机制等技术来进行注入 的。对于Spring而言,就是由Spring来控制对象的生命周期和对象之间的关系。
具体来说,Spring IOC的实现原理包括以下几个步骤:
- 配置Bean:在Spring配置文件中配置Bean的定义和属性,包括类名、属性、依赖关系等;
- 加载配置文件:Spring容器在启动时读取配置文件,解析配置文件中的Bean定义和属性;
- 创建Bean实例:根据配置文件中的Bean定义,Spring容器使用Java反射机制创建Bean实例;
- 注入属性:Spring容器根据Bean定义中的属性信息,使用Java反射机制将Bean需要依赖的其他Bean实例注入到当前Bean实例中;
- 容器管理Bean实例:Spring容器管理Bean实例的生命周期,包括创建、初始化、使用、销毁等。
通过IOC和DI的方式,Spring框架实现了应用程序中各个组件之间的解耦,使得应用程序更加灵活和易于扩展。
7️⃣ 什么是Spring IOC容器?
Spring 容器是 Spring 框架的核心。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。
Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。
在Spring中IOC容器的主要表现形式是 BeanFactory和 ApplicationContext这两个接口。这两个接口的具体实现类就可以看成是IOC容器在Spring中的具体体现。
BeanFactory提供了最基本的IOC和依赖注入功能,ApplicationContext继承了BeanFactory,在BeanFactory的基础上添加了很多新功能,主要包括国际化、事件分发机制(ApplicationEvent)、资源访问(Resource)等功能。在实际的开发过程中,一般都会选择ApplicationContext系列的容器实现。
8️⃣ 依赖注入(DI)是什么?有哪些方式完成依赖注入?优缺点是什么?
依赖注入(DI,Dependency Injection)是 spring 框架核心 IoC 的具体实现手段或方式。所谓依赖注入,即在运行期由容器将依赖关系注入到组件之中。
就是在运行期,由Spring根据配置文件,将其他对象的引用通过组件的提供的setter方法进行设定。
Spring 大量引入了Java 的Reflection机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件BeanFactory,以此作为其依赖注入机制的实现基础。
在Spring框架中,可以通过以下方式实现依赖注入:
-
构造器注入(Constructor Injection):通过构造方法来完成对依赖的注入。
通过添加@Component 或@Service 等注解使 bean受Spring容器管理,再将依赖以参数形式传递给构造函数。@Service public class UserServiceImpl implements UserService { private final UserMapper userMapper; @Autowired public UserServiceImpl(UserMapper userMapper) { this.userMapper = userMapper; } }
-
Setter方法注入(Setter Injection):在bean中创建setter方法,并在该方法上使用@Autowired、@Resource等注解,Spring会自动调用这些setter方法并注入需要的依赖项;
@Service public class UserServiceImpl implements UserService { private UserMapper userMapper; @Autowired public void setUserMapper(UserMapper userMapper) { this.userMapper = userMapper; } }
-
属性注入(Field Injection,也叫字段注入或变量注入):在bean中定义成员变量并将其标记为@Autowired或@Resource等注解,Spring会自动将相应的依赖对象注入到这些字段上;
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; //... }
以上就是各种依赖注入的实现方式。其优势及缺点如下:
实现方式 | 优点 | 缺点 |
---|---|---|
属性注入 | 方式简单,代码简洁 | 注入对象不能用final修饰; 可能会导致循环依赖,启动不报错,使用时才报错; 存在潜在隐患,不调用将无法发现 NullPointException异常; |
构造器注入 | 注入对象可以使用final修饰; 若存在循环依赖,spring项目启动的时候就会报错; 通过强制指明依赖注入来保证这个类的运行,防止NullPointerException; |
当有多个对象需要注入时,构造函数的代码臃肿; |
Setter方法注入 | 依赖注入中使用的依赖是可选的,注入的依赖可以为 null; 允许在类构造完成后重新注入; |
注入对象不能使用final修饰; |
其中,建议使用构造方法注入和setter方法注入,因为它更为清晰明了且不会导致循环依赖问题。而属性注入则容易引发一些设计和测试问题。
9️⃣ Spring Bean有哪几种作用域?有什么区别?
在Spring框架中,Bean作用域(scope)指的是在不同环境下创建和管理Bean时的生命周期。
一个Bean实例会有自己的作用域,而总共有以下5种的作用域情况:
-
Singleton(单例):一个IoC容器中只能存在一个实例,不同容器之间可以有不同的实例。这种bean范围是默认的,这种范围下不管接受到多少个请求,每个容器中只会有一个bean的实例;
-
Prototype(原型):每个请求都会创建一个新的实例,每次调用getBean()都会返回一个新的对象。这意味着每个客户端将获得一个新的原型实例,并且与之前连接的客户端没有关系;
-
Request(请求):仅适用于WebApplicationContext上下文中,表示为每个HTTP请求创建一个新的Bean实例。因此,对于同一次HTTP请求而言,任何对Bean的请求都将返回同一个Bean实例。然而,不同的HTTP请求将产生不同的Bean实例;
-
Session(会话)也仅适用于WebApplicationContext上下文中,表示为每个HTTP会话创建一个新的Bean实例。同一会话中的多个请求将共享同一个Bean实例;
-
GlobalSession(全局会话):仅适用于web应用程序,表示为每个全局HTTP会话创建一个新的Bean实例,通常只在使用Spring Portlet MVC时才使用。如果部署在Servlet环境下,该作用域没有区别于Session。
在实际应用中,正确选择和使用适当的作用域很重要。在大多数情况下,Singleton是最合适和高效的选项,也是默认作用域,它创建一个对象并在容器内共享该对象。Prototype每次请求都会创建一个新的实例,因此它可以防止线程安全问题。Request和Session将实例的作用域限制在HTTP请求/会话期间。GlobalSession作用域基本不使用,只适用于特殊的portlet场景。
🔟 详细讲一下Spring AOP及其实现原理?
Spring AOP(面向切面编程)是Spring框架的一个核心功能,它允许将不同但相关的业务逻辑组件解耦,从而提高了应用程序的可维护性和可重用性。
通过使用Spring AOP,我们可以将与业务逻辑无关的各种横向关注点(如日志记录、事务管理、安全性、缓存等)从业务逻辑中分离出来,避免代码重复,并使得代码更加清晰易懂。
在Spring AOP中,切面(Aspect)是对横向关注点的抽象。切面包含了具体的切点(Pointcut)和通知(Advice),其中切点定义了何时织入通知,而通知则定义了何种行为需要执行。
其工作流程具体如下:
-
定义切入点:我们需要定义一个或多个切入点以便确定哪些方法需要被拦截处理。切入点指定的是方法的名称和任意参数类型;
-
编写通知(增强):在Spring AOP中,通知(Advice)是应用在切入点之前或者之后执行的一种代码块。Spring AOP支持以下5种通知类型:
- 前置通知(Before advice):在目标方法执行前执行;
- 后置通知(After advice):在目标方法执行后执行;
- 返回通知(After returning advice):在目标方法执行完并返回结果之后执行;
- 异常通知(After throwing advice):在目标方法抛出异常后执行;
- 环绕通知(Around advice):包围目标方法的通知,可以在目标方法执行前、执行后、执行返回或抛出异常时执行。
-
创建代理对象:在运行期间,Spring AOP会为目标对象创建一个代理对象。代理对象通过Spring容器返回给客户端;
-
执行拦截:在调用代理对象的方法时,Spring AOP自动检查方法是否需要拦截(即是否匹配切入点),如果匹配,则执行相应的通知代码块,然后再调用原始的目标方法。
而从原理上来说,Spring AOP是基于动态代理的实现方式来实现切面编程的。针对不同类型的bean,Spring使用JDK动态代理或CGLIB(Code Generation Library)字节码生成技术来创建代理对象。
其中,如果目标对象实现了至少一个接口,则Spring AOP将使用JDK动态代理。基本原理是利用 Java 的反射机制生成目标对象的代理对象,通过调用代理对象之前调用“前置通知”拦截方法,进行切面编程。
如果目标对象没有实现任何接口,则 Spring AOP 将使用CGLIB(Code Generation Library)库来实现代理。基本原理是在内存中构建出目标对象子类的字节码并载入 JVM 中,生成目标对象的代理对象,也通过调用代理对象之前调用“前置通知”拦截方法,同样可以实现切面编程。
Spring AOP 使用 BeanPostProcessor 在应用中动态创建和织入切面。BeanPostProcessor 拦截容器创建的对象,如果该对象匹配被代理的对象,则会根据上面的两种方式其一,来创建一个新的代理对象并返回。通过使用 BeanPostProcessor,AOP 识别它需要拦截的 bean,并且将切面编织到相应的代码中。
因此,在 Spring AOP 中,BeanPostProcessor 扮演着非常重要的角色。它提供了一种机制,使开发人员可以对 Spring IOC 容器创建的每个 bean 进行定制化处理,进而进行 AOP 代理的创建和织入。
图片来源:
Spring Framework 官网
Spring、SpringBoot全家桶技术栈知识点汇总(欢迎收藏)
Spring系列(一)、Spring入门及七大模块
springboot分析-spring IOC原理拆解和spring MVC模块分析
🎁 小山赠书活动
书籍详情可以去某当、某宝、某东各个网站搜索书籍名称查看~
没有自己中意的可以自选噢,自选规则查看下文
🍻 朋友们,千粉福利来啦!
《小山劝学第1期》 👏 👏 👏
赠书说明:图示图书中任选一本或者不限制(¥100内的书籍自主选择,可以是 非软件行业的书噢,但只限一本噢~)
参与方式:关注+点赞+收藏,评论区评论 “勤能补拙,IT之路,共同进步!”(记得不要漏掉噢,否则抽奖无效~)
开奖时间:2023-06-16 12:00:00
开奖名额:3名
通知方式:开奖后我会向中奖用户发起私信并把结果公布在评论区,不弄虚作假哈~