Spring面试题
- *一.基础知识*
- 零.ApplicationContext refresh的过程
- 1.prepareRefresh
- 2.obtain(获得)FreshBeanFactory
- 3.prepareBeanFactory
- 4.postProcessBeanFactory
- 5.invokeBeanFactoryPostProcessors![在这里插入图片描述](https://img-blog.csdnimg.cn/88035e78363e4c0e89a4cac4547df3a7.png)
- 6.registerBeanPostPocessor![在这里插入图片描述](https://img-blog.csdnimg.cn/92ef73989633470a87a6b659edc1b4f6.png)
- 7.initMessageSource
- 8.initApplicationEventMulticaster(事件广播器)
- 9.onRefresh
- 10.registerListeners
- 11.finishBeanFactoryInitialization
- 12.finishRefresh
- 一、说说你对Spring的理解?
- 二、Spring由哪些模块组成?
- 三.在Spring中有几种配置Bean的方式?(高频)
- 四.BeanFactory和ApplicationContext有什么区别?(高频)
- 四.一 spring BeanFactory和FactoryBean区别
- 五.Spring框架中的单例bean是线程安全的吗?(高频)
- 六.Spring Bean有哪些作用域,它们之间有什么区别?(高频)
- 七、你用过哪些重要的Spring注解?(高频)
- 八.请解释一下spring框架有哪些自动装配模式,它们之间有何区别?(高频)
- *二.aop原理*
- 三.事务管理
- 1.spring事务的实现方式以及原理?(高频)
- 2.什么是事务的传播行为?在Spring框架中都有哪些事务的传播行为?
- 3.spring如何管理事务的?(高频)
- ①.PlatformTransactionManager:平台事务管理器,主要用于平台相关事务的管理。
- ②.TransacitonDefinition:事务定义信息,用来定义事务相关属性,给事务管理器PlatformTransactionManager使用
- ③TransationStatus:事务具体运行状态,事务管理过程中,每个时间点事务的状态信息。
- 4.spring事务什么情况下会失效?(高频)
- ①数据库引擎不支持事务:(一般不会出现)
- ②bean没有被Spring 管理(一般不会出现)
- ③方法不是public的:(一般也不会出现)
- ④抛出受检异常导致事务失效
- ⑤异常在方法内部通过try...catch处理掉了
- ⑥调用事务类本类的方法
- ⑧事务的原子性只覆盖增删改,不覆盖查
- ⑨@Transaction和Synchronized在同一个类同时使用导致 事务失效
- ⑩启动类没有开启平台事务管理器
- ⑩① 父子容器导致事务失效(springBoot项目不会出现)
- 5.spring事务隔离级别就是数据库的隔离级别
- 四.循环依赖
- 五.线程安全
一.基础知识
零.ApplicationContext refresh的过程
(刷新)初始化spring容器
beanFactory是创建Bean的,application在bean的管理上借助了beanFactory,虽然它是继承了beanFactory的,但是它还是组合了BeanFacotory
1.prepareRefresh
2.obtain(获得)FreshBeanFactory
3.prepareBeanFactory
4.postProcessBeanFactory
这一步是模板设计模式,交由子类扩展
5.invokeBeanFactoryPostProcessors
6.registerBeanPostPocessor
常见Bean后处理器
7.initMessageSource
8.initApplicationEventMulticaster(事件广播器)
9.onRefresh
模板设计模式,空实现,交由子类扩展
10.registerListeners
11.finishBeanFactoryInitialization
12.finishRefresh
一、说说你对Spring的理解?
1、Spring是一个开源框架,主要是为简化企业级应用开发而生。
① 控制反转(IOC):
Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,
这就是控制反转的思想。解除类与类之间的耦合
② 依赖注入(DI):
Spring使用Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。
③ 面向切面编程(AOP):(切点+通知)
在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事务管理,记录日志等公用操作处理的过程就是面向切面编程的思想。
切入点:目标对象中要被增强的方法;
通知:要增强的功能;
连接点:目标对象中可以被增强的方法;
切面:切入点和通知的组合
2.在Spring中,所有管理的都是JavaBean对象
而BeanFactory和ApplicationContext就是Spring框架的那个IOC容器,现在一般使用ApplicationContext,其不但包括了BeanFactory的作用,同时还进行了更多的扩展。ApplicationContext,其不但包括了BeanFactory的作用,同时还进行了更多的扩展。
二、Spring由哪些模块组成?
第一个:核心容器(Spring Core)
核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。
Spring Context(应用上下文):
应用上下文: 是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能
第二个:数据访问/集成
1.SpringDao(JDBC和Dao模块)
JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
2.Spring ORM(对象实体映射)
Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事务和DAO异常层次结构。
第三个:Web
Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
1.Spring Web MVC(MVC模块)
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型由JavaBean构成,存放于model当中,而视图是一个接口,负责实现模型,控制器表示逻辑代码,有controller的事情。
Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。
第四个:AOP (面向切面编程、 工具、消息和测试模块 )
是面向对象编程的有效补充和完善,Spring的AOP是基于动态代理实现的
三.在Spring中有几种配置Bean的方式?(高频)
1、基于XML的配置
2、基于注解的配置
3、基于Java类的配置
四.BeanFactory和ApplicationContext有什么区别?(高频)
1、BeanFactory:(懒加载)BeanFactory在启动的时候不会去实例化Bean,当从容器中拿Bean的时候才会去实例化;
2、ApplicationContext:(启动就加载)ApplicationContext在启动的时候就把所有的Bean全部实例化了。
它还可以为Bean配置lazy-init=true来让Bean延迟实例化(实现懒加载);
ApplicationContext是BeanFactory的子接口
四.一 spring BeanFactory和FactoryBean区别
BeanFactory是一个factory,是spring的IOC的容器;
FactoryBean是spring创建bean的一种方式,是将bean放入ioc容器的一种方式。
五.Spring框架中的单例bean是线程安全的吗?(高频)
不是线程安全的
当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求对应的业务逻辑(成员方法),此时如果该处理逻辑中有对该单例状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。
Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。
如果你的bean有多种状态(多个自定义成员变量)的话(比如 View Model对象),就需要自行保证线程安全。
最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype(原型)”。
六.Spring Bean有哪些作用域,它们之间有什么区别?(高频)
1、singleton :这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护 。
2、prototype :(多例)原形范围与单例范围相反,为每一个bean请求提供一个实例 。
3、request :在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后, bean会失效并被垃圾回收器回收 。
4、session:与请求范围类似,确保每个session中有一个 bean 的实例,在session过期后, bean会随之失效 。
七、你用过哪些重要的Spring注解?(高频)
1.IOC相关的注解
①.创建Bean注解
@Component @Controller @Service @Repository
②.依赖注入注解
@Autowired
@Qualifier
@Value,使用方式:
③.作用范围注解
@Scope
单例和多莉
singleton
prototype
④.条件装配
@Conditional
⑤.配置类 和 组件扫描
@Configuration -> (第三方jar包中的类)
@Bean
@ComponentScan
@Import
6.延迟加载
@Lazy,标注在类上,表示延迟创建bean。第一次使用创建
@Lazy,标注在属性或者方法参数上,先给代理对象
7.配置文件加载
@PropertySource
2.核心
@Order控制Bean的执行顺序
3.事务
@EnableTransactionManager
@Transactional
4.任务调度,异步
@Schaduled
@EnableShaduling
@Aync
@EnbaleAync
5.切面注解
@EnableAspectJAutoProxy
@Aspect
@PointCut
@Before
@After
@Around
@AferRuning 返回后通知
@AferThrowing 异常后通知
6.spring cache相关注解(用注解代替操作缓存的代码,简化开发)
@EnableCaching
开启缓存
@Cachable
判断没有的话才存缓存;
@CacheEvict(删除缓存)
@CachePut
不判断,直接添加缓存
八.请解释一下spring框架有哪些自动装配模式,它们之间有何区别?(高频)
spring的自动装配功能的定义:无须在Spring配置文件中描述javaBean之间的依赖关系(如配置、)。
自动装配模式:
1、no:这是 Spring 框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在 bean 定义中用标签明确的设置依赖关系 。
2、byName:该选项可以根据bean名称设置依赖关系 。 当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹
配的bean。 如果找到的话,就装配这个属性,如果没找到的话就报错 。
3、byType:该选项可以根据 bean 类型设置依赖关系 。 当向一个 bean 中自动装配一个属性时,容器将根据 bean 的类型自动在在配置文件中查询一个匹配的 bean。 如果找到的话,就装配这个属性,如果没找到的话就报错 。
4、constructor :构造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean ,那么将会抛出异常 。
5、default:该模式自动探测使用构造器自动装配或者byType自动装配 。 首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的 构造器或者是无参构造器,容器就会自动选择 byTpe 的自动装配方式 。
比如如下注入:
可以改造为:
二.aop原理
1.spring中aop的底层是怎么实现的?(高频)
Spring中AOP底层的实现是基于动态代理进行实现的。
常见的动态代理技术有两种:JDK的动态代理和CGLIB。
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法进行增强,但是因为采用的是继承,所以该类或方法最好不要声明为final,对于final类或方法,是无法继承的。
Spring如何选择是用JDK还是cglib?
1、当bean实现接口时,会用JDK代理模式
2、当bean没有实现接口,会用cglib实现
3、可以强制使用cglib,配置一个属性 paroxy-target-class为true;
这个是配置文件,也可以在配置类中使用
2.spring aop机制都有哪些应用场景?(高频)
①权限验证,
②事务管理,
③记录日志
三.事务管理
1.spring事务的实现方式以及原理?(高频)
Spring支持编程式事务管理和声明式事务管理两种方式!
编程式事务控制
需要使用TransactionTemplate来进行实现,这种方式实现对业务代码有侵入性,因此在项目中很少被使用到。
声明式事务管理
声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中。
2.什么是事务的传播行为?在Spring框架中都有哪些事务的传播行为?
Spring的事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法对事务的态度。
举例:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
管理者,协调者
Spring中提供了7种事务的传播行为:
1、REQUIRED(要求):
如果当前没有事务,就创建一个新事务,
如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、REQUIRES_NEW(新要求):
无论当前存不存在事务,都创建新事务。
3、SUPPORTS(支持):
如果当前存在事务,就加入该事务,
如果当前不存在事务,就不创建事务。
4、NOT_SUPPORTED(不支持):
如果当前存在事务,就把当前事务挂起。
5、MANDATORY(义务):
如果当前存在事务,就加入该事务,
如果当前不存在事务,就抛出异常。
6、NEVER(从不):
以非事务方式执行,如果当前存在事务,则抛出异常。
7、NESTED(嵌套的):
如果当前存在事务,则在嵌套事务内执行。
如果当前没有事务,就创建事务执行。
3.spring如何管理事务的?(高频)
Spring事务管理主要包括3个接口,Spring事务主要由以下三个共同完成的:
①.PlatformTransactionManager:平台事务管理器,主要用于平台相关事务的管理。
主要包括三个方法:
① commit:事务提交。
② rollback:事务回滚。
③ getTransaction:获取事务状态。
②.TransacitonDefinition:事务定义信息,用来定义事务相关属性,给事务管理器PlatformTransactionManager使用
主要包含的方法:
① getIsolationLevel:获取隔离级别。
② getPropagationBehavior:获取传播行为。
③ getTimeout获取超时时间。
④ isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)
③TransationStatus:事务具体运行状态,事务管理过程中,每个时间点事务的状态信息。
主要包含的方法:
① hasSavepoint():返回这个事务内部是否包含一个保存点。
② isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚。
③ isNewTransaction():判断当前事务是否是一个新事务。
4.spring事务什么情况下会失效?(高频)
①数据库引擎不支持事务:(一般不会出现)
这里以 MySQL为例,其MyISAM引擎是不支持事务操作的,InnoDB才是支持事务的引擎,一般要支持事务都会使用
②bean没有被Spring 管理(一般不会出现)
③方法不是public的:(一般也不会出现)
@Transactional只能用于public的方法上,否则事务不会失效。
④抛出受检异常导致事务失效
⑤异常在方法内部通过try…catch处理掉了
⑥调用事务类本类的方法
rollback=exception
⑧事务的原子性只覆盖增删改,不覆盖查
用select … for update
⑨@Transaction和Synchronized在同一个类同时使用导致 事务失效
增加synchronized范围,
手动开启和提交事务
⑩启动类没有开启平台事务管理器
⑩① 父子容器导致事务失效(springBoot项目不会出现)
子容器扫描过大,把未加事务的service扫描进来
解决:
各扫描各的
不要用父子容器,放在同一个容器中
5.spring事务隔离级别就是数据库的隔离级别
read uncommitted(读未提交)
read committed(读已提交、不可重复读)
repeatable read(可重复读)
serializable(可串行化)
数据库的配置隔离级别是Read Commited,
而Spring配置的隔离级别是Repeatable Read,
这时隔离 级别是以Spring配置的为准,如果spring设置的隔离级别数据库不支持,效果取决于数据库。
四.循环依赖
1.请解释一下spring bean的生命周期?
Spring Bean的生命周期如下图所示:
①、 阶段1:处理名称,检查缓存
②、处理父子容器
③.dependsOn
④.按Scope创建bean
⑤.创建Bean
⑥.类型转换
⑦.销毁bean
2.spring中的aop是在bean生命周期的哪一步实现的?
在创建Bean的初始化阶段实现的
3.什么是Spring的循环依赖?(高频)
简单的来说就是A依赖B的同时,B依赖A。在创建A对象的同时需要使用的B对象,在创建B对象的同时需要使用到A对象。如下代码所示:
set循环依赖
Spring解决循环依赖是通过三级缓存,对应的三级缓存如下所示:
缓存 源码名称 作用
一级缓存 singletonObjects 单例池; 缓存已经经历了完整声明周期, 已经初始化完成的bean对象
二级缓存 earlySingletonObjects 缓存早期的bean对象(生命周期还没有走完)
三级缓存 singletonFactories 缓存的是ObjectFactory, 表示对象工厂, 用来创建某个对象的(可以创建目标对象,也可以创建代理对象)
一级缓存解决Bean的单例,单不能解决循环依赖问题
三级缓存可以解决循环依赖,但不能解决循环依赖有代理的情况
加入二级缓存配合三级缓存,可以解决循环依赖有代理情况
构造循环依赖
解决思路:
用ObjectFactory工厂对象来解决;
Providor工厂是ObjectFactory工厂的子类,也可以解决。
五.线程安全
1.Spring框架中的单例Bean是线程安全的么
Spring中的Bean默认是单例模式的
如果是无状态的,那就是安全的,
如果Bean是有状态的(自己定义了成员变量),那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作
用域 把 "singleton"改为’‘protopyte’ ,这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
2.spring如何保证⾼并发下Controller线程安全
不要在bean中声明任何有状态的实例变量或静态变量,如果必须如此;
那么就使用ThreadLocal把变量变为线程私有的,如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用synchronized、lock、CAS等这些实现线程同步的方法了。