Spring面试题总结及答案
2020-01-13 10:09
162 查看
Spring
面试总结
Spring
是什么?
Spring框架是一个
java平台,提供全面基础设施支持开发
java应用程序。
Spring
的主要模块有哪些?
Spring Code
:基础模块,主要提供IOC
和DI
功能。Spring Aspects
:该模块对与AspectJ
集成提供支持。Spring AOP
:提供面向切面编程的实现。Spring JDBC
:提供java
数据库连接。Spring JMS
:java
消息服务。【与远程调用机制以及REST接口类似】Spring ORM
:用于支持Hibernate
等ORM
工具。Spring Web
:为创建Web
应用程序提供支持。Spring Test
:提供了对JUnit
和TestNG
测试支持。
Spring
的优点
低侵入式设计,代码污染低,低耦合,复用性高,对主流框架的集成支持
aop
的理解
aop是面向切面编程,是面向对象的一种补充,用于将那些与业务无关,却对多个对象有影响的公共行为和逻辑,抽取并封装为一个可重用的公共模块,减少重复代码降低模块间的耦合度,提高系统的可维护性
代理模式
静态代理和动态代理
-
静态代理
AspectJ
也称编译时增强,静态代理就是编译阶段生成代理类,将切面织入
java
字节码中,运行后就是增强之后的aop
对象 -
动态代理
Spring Aop
动态代理就是不去修改字节码,而是每次运行时在内存中为方法生成一个
aop
对象,这个对象包含了目标对象的全部方法,在特定的切点做了增强处理,并回调原对象的方法动态代理基于
JDK
动态代理和CJLIB
动态代理JDK
动态代理JDK
动态代理只提供接口的代理,不支持类的代理 -
CJLIB
动态代理CJLB
时通过继承的方式做的动态代理,如果某个类被标记为final
,是无法使用CJLIB
做动态代理
Spring AOP默认是
JDK动态代理。
静态代理和动态代理的区别
区别在于生成
aop代理的时机不同,相对来说
AspectJ的静态代理有更好的性能,但是
AspectJ需要特定的编译器处理,而
Spring Aop不需要特定的编译器处理
IOC
的理解
IOC控制反转,不是一种技术,而是一种设计思想。是创建对象的控制权和转移,以前创建对象的时机和主动权是由自己把控的,而现在是把这种权力转移到spring容器中,由容器根据配置文件去创建实例和管理各个实例间的依赖关系,对象与对象的松散耦合,也就是
IOC让对象的创建不用去
new了,由
spring自动生产,利用
java的反射机制,根据配置文件运行时动态的去创建对象和管理,并调用对象的方法
- 使用
java
反射机制的几种方法 通过全限定类名 - 获取构造器对象,通过构造器
new
出来 - 通过
class
对象创建一个实例对象 - 通过
class
对象获得一个属性对象 - 通过
class
对象获得一个方法对象
ioc控制反转理解:
-
谁控制了谁,控制了什么:
ioc
控制了对象,控制了外部资源的获取
什么是反转?
-
传统的程序直接获取依赖对象,也就是正转。
ioc容器帮我们创建对象及注入依赖
为何是反转?
- 是因为容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象。
DI依赖注入理解:
形象的说,由容器动态的将某个依赖关系注入到组件中。
- 谁依赖了谁:
应用程序依赖了
ioc
容器
-
因为需要
ioc容器来提供对象需要的外部资源
-
是
ioc容器注入了应用程序某个对象,应用程序依赖的对象
-
就是注入了某个对象所需要的外部资源(包括对象,资源,常量数据等)
ioc为什么要和
DI同时出现
- 因为他们是同一概念不同角度的描述
IOC
的注入
- 构造器注入
setter
方法注入- 注解注入
【构造器参数实现强制依赖】
【setter方法实现可选依赖】
Spring
中bean
的作用域
singleton:
唯一bean实例,Spring中的bean默认都是单例。
prototype:
-
每次请求都会创建一个新的
bean实例。(多例)
request:
-
每次
HTTP请求都会产生一个新的
bean,该
bean仅在
HTTP Request内有效。
session:
-
每次
HTTP都会产生一个新的
bean,该
bean仅在
HTTP Session内有效。
global-session:
-
全局session作用域,仅仅在基于
Portlet的
Web应用中才有意义,
Spring5中已经没有了。
BeanFactory
和AppplicationContext
的区别?
BeanFactory
是spring
最底层的接口,包含了各种bean
的定义,管理bean
的加载,实例化,控制bean
的生命周期,维护bean
之间的关系,而ApplicationContext
接口是BeanFactory
的派生,除了有BeanFactory
所有的功能外,还有更加完整的框架功能:ApplicationContext
继承了MessageSource
- 统一的文件访问方式
- 可以在监听器中注册
bean
的事件 - 同时加载多个配置文件
- 载入多个有继承关系的上下文,让每一个上下文都专注与一个特定的层次
BeanFactory
是延迟加载的方式来注入bean
,如果有异常,只有在使用bean
的时候,才会抛出,不能及时发现存在spring配置的问题。而ApplicationContext
是容器启动时一次性创建所有bean
,如果有问题,在启动时我们就可以发现了,有利于检查所有依赖属性是否注入(ApplicationContext
启动后预载入所有的单实例bean
)BeanFactory
通常是以编程的方式进行创建,而ApplicationContext
可以以声明的方式进行创建(如:ContextLoader
)BeanFactory
和ApplictionContext
都支持BeanPostProcessor
、BeanFactoryPostProcessor
的使用,但BeanFactory
是手动注册,而ApplicationContext
是自动注册
Spring Bean
的生命周期
Bean容器找到配置文件中Spring Bean的定义
。Bean容器利用Java Reflection API创建一个Bean的实例
。如果涉及到属性值,利用set()方法设置一些属性值
。如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean名字
。如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象实例
。如果Bean实现BeanFactoryAware接口,调用setBeanClassFactory()方法,传入ClassLoader对象实例。(如果实现了其他Aware接口,就调用相应的方法)
如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessorBeforeInitialization()方法
。如果Bean实现了InitializingBean接口, 执行afeterPropertiesSet()方法
。如果Bean在配置文件中定义了包含init-method属性,执行指定的方法
。如果有何加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization()方法
。当要销毁Bean的时候,如果Bean实现了DisposableBena接口,执行destroy()方法
。当要销毁Bean的时候,如果Bean在配置文件中的定义包含destory-method属性,执行指定方法
。
怎么重载Bean
生命周期重要的方法?
init-method
和destroy-method
属性,可以用他们来定制初始化方法和注销方法- 相应的注解:
@PostConstuct
@PreDestroy
Spring
框架中的单例Bean
是否线程安全
大部分时候我们的系统中并没有使用多线程,所以很少去关注这个问题,单例
Bean是存在线程问题的,主要是因为当多个线程对这个对象的非静态成员变量进行写操作时会存在线程安全问题。
有常用的俩种解决方案:
- 在
Bean
对象中尽量避免定义可变的成员变量。(并不现实) - 在类中定义一个
ThreadLoad
成员变量,把需要可变的成员变量保存在ThreadLoad
中。(推荐的一种方式)
Spring
事务的管理方式
- 编程式事务:在代码中硬编码。(不推荐使用)
- 声明式事务:在配置文件中配置。(推荐使用)
基于
XML
的声明式事务。 - 基于注解的声明式事务。
Spring
事务中的隔离级别有哪几种?
在
TransactionDefinition接口中定义了五个表示隔离级别的常量
ISOLATION_DEFAULT
:使用后端数据库默认的隔离级别,MySQL
默认采用REPEATABLE_READ
隔离级别,Oracle
默认采用的READ_COMMITTED
隔离级别。ISOLATION_READ_UNCOMMITTED
:最低级隔离级别,允许读取尚未提交的数据变更,可能会导致脏读,幻读,不可重复读。ISOLATION_READ_COMMITTED
:允许读取并发事务已提交的数据,可以阻止脏读,但是幻读,不可重复读仍有可能发生。ISOLATION_REPEATABLE_READ
:对同一个字段多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但是幻读仍有可能发生。ISOLATION_SERIALIZABLE
:最高的隔离级别,完全服从ACID的隔离级别。所有事务依次逐个执行,这样事务之间就完全不可能产生干扰。可阻止脏读,不可重复读,幻读。但是会严重影响程序的性能通常情况不会用到该级别。
Spring事务中的传播行为
在
TransactionDefiniton接口中定义了八个表示事务传播行为的常量
支持当前事务的情况:
PROPAGATION_REQUIRED
:如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。PROPAGATION_SUPPORTS
:如果当前存在事务,则加入该事务,如果当前没有事务,则以非事务的方式继续运行。PROPAGATION_MANDATORY
:如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常。(mandatory:强制性)
不支持当前事务的情况:
PROPAGATION_REQUIRES_NEW
:创建一个新的事务,如果当前存在事务,则把事务挂起。PROPAGATION_NOT_SUPPORTED
:以非事务的方式运行,如果当前存在事务,则把事务挂起。PROPAGATION_NEVER
:以非事务的方式运行,如果当前存在事务,则抛出异常。
其他情况:
PROPAGATION_NESTED
:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行,如果当前没有事务,则取值等价于PROPAGATION_REQUIRED。
Spring中用到了那些设计模式?
-
工厂设计模式:
Spring
使用工厂代理模式通过BeanFactory
和ApplicationContext
创建对象。 -
代理设计模式:
Spring AOP
功能实现。 -
单例设计模式:
Spring
中的Bean
,默认都是单例的。 -
模板方法模式:
Spring
中的jdbcTempalte
等以Template
结尾的对数据库操作的类,就使用到了模板模式。 -
包装器设计模式:当我们的项目需要连接多个数据库的时候,而且不同的客户在每次访问中会去访问不同的数据库,这种模式可以根据客户的需求动态的切换不同的数据源。
-
观察者模式:
Spring
事件驱动模型就是观察者模式很经典的一个应用。什么是事件驱动模型?
是一种对象间一对多的关系,就像交通信号灯,信号灯是目标(也就是一的一方),行人是多方,行人需要注意观察信号灯的变化,当信号灯变为绿色的时候(也就是目标发送了改变),行人就知道这时候该过马路了(也就是订阅者可以接受到改变)。观察者怎么处理,目标不会干涉,这就松散的他们之间的耦合。就像绿灯的时候行人怎么走,是直着走还是弯着走,是走得快还是走的慢,目标都不会管。
适配器模式:
Spring AOP的增强通知使用到了适配器模式,
Spring MVC也用到了适配模式来适配
Controller。
等等…
@Component
和@Bean
的区别是什么?
- 作用对象不同
@Component
作用与类。 @Bean
作用与方法上。
@Component注解扫描来自动侦测和自动装配到
Spring容器中。
-
可以使用
@ComponentScan来定义要扫描的路径。
@Bean注解通常实在标有该注解的方法中产生这个
Bean,告诉
Spring容器,当我需要他的时候在给我。
@Bean比
@Component的自定义性强,很多地方只能用
@Bean来注册
Bean。比如当我们需要使用第三方类库的类的时候,就只能通过
@Bean来实现。
将一类声明为Spring
的Bean
的注解有哪些?
一般我们用
@Autowired注解去自动装配
Bean,而想要把一个类标识为可以使用
@Autowired注解自动装配的
Bean,可以使用如下注解:
@Component
注解:通用注解,可以标注任意类。@Repository
注解:对应持久层,也就是dao
层,主要用于数据库的相关操作。@Service
注解:对应服务层,也就是service
层,主要涉及一些复杂的逻辑,需要用到dao
层(@Autowired
注入)@Controller
注解:对应控制层,也就是Controller
层,主要用于接受用户请求并调用service
层的方法返回数据给前端页面。
什么是装配?
装配(
Bean装配)就是在
Spring容器中把
Bean组装到一起,前提是容器要知道
Bean的依赖关系,如何通过依赖注入把他们装配到一起。
什么是自动装配?
Spring容器能够自动装配相互合作的
Bean,容器不需要使用
<constructor-arg>和
<property>配置,能通过
Bean工厂自动处理
Bean之间的协作。
不同方式的自动装配
有五种:
no
:默认不自动装配,可以通过ref属性来进行装配。byName
:通过参数名自动装配。byType
:通过参数类型自动装配。construtor
:这个方式类似于byType
,是需要提供给构造器参数。autodetect
:首先尝试使用construtor
来自动装配,如果无法工作,则使用byType
方式。
自动装配的局限性
- 重写:需要使和配置定义依赖,总要重写自动装配。
- 基本数据类型:不能自动装配简单的属性,如基本数据类型,String还有类。
- 模糊特性:自动装配不如显示装配精确,建议使用显示装配。
可以在Spring中注入一个null和一个空字符串吗?
答:可以。
yType`,是需要提供给构造器参数。
autodetect
:首先尝试使用construtor
来自动装配,如果无法工作,则使用byType
方式。
自动装配的局限性
- 重写:需要使和配置定义依赖,总要重写自动装配。
- 基本数据类型:不能自动装配简单的属性,如基本数据类型,String还有类。
- 模糊特性:自动装配不如显示装配精确,建议使用显示装配。
可以在Spring中注入一个null和一个空字符串吗?
答:可以。
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 49个Spring经典面试题总结,附带答案!
- Spring经典面试题总结,附带答案!
- Spring面试题总结的很全面,附带超详细答案
- 总结Java常见面试题和答案
- Struts,Spring,Hibernate面试题总结
- 69个经典Spring面试题和答案
- Spring面试题和答案
- Java高级工程师面试题总结及参考答案
- .NET 面试题总结 (附有参考答案) 第2部分
- 69道Spring面试题和答案
- 69道Spring面试题和答案
- 69个终极Java Spring的面试题及答案,你绝对值得珍藏!
- 69道Spring面试题和答案
- Java高级工程师面试题总结及参考答案,大厂 HR 如何面试
- Struts,Spring,Hibernate面试题总结
- 69 个经典 Spring 面试题和答案
- 69道Spring面试题和答案
- 知名小码农呕心沥血总结的Java面试题(带全部答案)
- .NET 面试题总结 (附有参考答案) 第1部分
- 互联网公司校招Java面试题总结及答案——招银科技