7、Spring高频面试题

1、谈谈你对SpringIOC的理解
​ IOC,也叫控制反转, 对象以前是我们程序员自己new的,但是现在对象都是由Spring创建并放入到了IOC容器中,如果需要使用某个对象的时候直接从容器中获取;

​ 两个细节:1、Spring通过哪种方式创建的:反射

                    2、创建的对象放入到哪里了:ConcurrentHashMap,作为IOC容器

2、Spring中有哪些依赖注入方式

依赖注入指的是Spring给对象中属性进行赋值的过程,主要包括两种方式:

 1、@Autowired :根据类型注入

  2、构造器依赖注入:构造器注入是指容器调用一个类的构造器创建对象时,直接传入给属性赋值

Setter方法注入:Setter方法注入是指容器在创建对象完成后,通过调用属性的Setter 方法,可以属性赋值,这种是早期有xml配置时经常用。

3、你用过哪些Spring注解
我们常用的Spring注解主要分类下面几大类:

1、创建对象:@Component、@Controller、@Service、@Repository

​ 它们都可以标注在自己开发的类上,Spring会使用注解标注的类创建出对象,然后放入容器

2、依赖注入:@Autowired

​ 标注在属性或者属性对应的set方法上,Spring会根据被标注属性的类型自动对属性进行赋值

3、依赖注入:@Qualifier

​ 和@Autowired一块使用,在同一类型的bean有多个的情况下Spring会根据name进行选择注入

4、配置类:@Configuration、@Bean

​ 主要标注在配置类中,用于声明配置类和向Spring容器中放入一些配置有关的对象

5、当然还有一些平时用的不是特别多的

​ 比如:声明注解扫描的@ComponentScan,声明Bean的作用域的@Scope,用于切面编程的@Around,@Pointcut等等

4、SpringBean的作用域有几种
在Spring中作用域是用来对象的存活范围的,它支持5种作用域

第一种是单例,配置为单例的对象会跟随Spring容器创建而创建,跟随Spring容器销毁而销毁,在Spring容器中无论获取多少次单例对象,得到的都是同一个,这也是Spring中的对象的默认作用域

第二种是多例,配置为多例的对象在每次获取的时候才会创建,而且每次获取到的都不一样

还有三种分别是request、session和application,目前已经基本不再使用

​ 其实,在我们平时的开发过程中,对象基本上都是配为单例的,这样可以有效的节省资源,只有单例对象存在线程安全问题时,才考虑调整为多例。

5、Spring中的bean线程安全吗
Spring中的Bean主要分为单例和多例,默认是单例的,如果单例bean有成员变量,多线程操作时要同时修改这个成员变量的值就有可能出现线程不安全情况,解决方式有两种: 

 1)将Bean的作用域由单例改为多例,这样虽然解决了,但是不推荐,因为每个线程就产生一个对象,并发量大的时候可以造成内存溢出;
 2)将需要的可变成员变量保存在ThreadLocal中, ThreadLocal本身就具备线程隔离的特性,这就相当于为每个线程提供了一个独立的变量副本,每个线程只需要操作自己的线程副本变量,从而解决线程安全问题。


6、谈谈你对SpringAOP的理解
​ AOP,又叫面向切面编程,就是在不改变原代码的基础上对原方法做增强,比如做事务管理、日志、性能监视、安全检查等等;

Spring AOP是基于动态代理的,它底层同时支持JDK和CGLIB的代理方式,并且会根据被代理类是否有接口自动选择最合适的代理方式

7、AOP的代理有几种方式
JDK动态代理和CGLIB动态代理

JDK动态代理只能对有接口的类进行代理,而且效率较高
CGLIB可以对任意的类进行动态代理,但是效率上不如JDK
因此在进行代理时,如果被代理类有接口,就用JDK;如果没有接口,就用CGLIB

8、Spring的通知类型有哪些

四大通知+环绕通知 总共有5种

四大通知指的是

前置通知:在某切点之前执行的通知
返回后通知:在某切点正常完成后执行的通知
抛出异常后通知:在某切点抛出异常退出时执行的通知
后置通知:在某切点退出的时候执行的通知(不论是正常返回还是异常退出)

环绕通知:可以替代四大通知

9、Spring事务传播行为有几种
事务传播行为是为了解决业务层方法之间互相调用的事务问题。

当事务方法被另一事务方法调用时,必须指定事务应该如何传播。

例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

Spring支持7个种事务传播行为的:

必须事务:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务

必须新事务:创建一个新的事务,如果当前存在事务,则把当前事务挂起

强制事务:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常

支持事务:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行

不支持事务:以非事务方式运行,如果当前存在事务,则把当前事务挂起

强制无事务:以非事务方式运行,如果当前存在事务,则抛出异常

嵌套事务:如果当前存在事务,则创建一个当前事务的嵌套事务来运行;如果当前没有事务,则创建一个事务

嵌套事务是已存在事务的一个子事务,嵌套事务开始执行时,将取得一个保存点,

如果这个嵌套事务失败,将回滚到此保存点

嵌套事务是外部事务的一部分,只有外部事务结束后它才会被提交

10、Spring中的事务是如何实现的

在方法上添加@Transactional注解就可以实现控制事务,是基于Spring的AOP机制的

他的原理就是要保证在同一个方法中使用的是同一个Connection对象,并且把这个Connection对象的事务提交方式改成手动提交,这样可以统一管理事务的提交和回滚

11、什么情况下会导致事务失效  方法上明明有@Transactional但是事务没有生效
 1)、 事务的传播行为会导致事务失效,举例 A方法调用B方法时 B方法的事务传播行为是REQUIRES_NEW A方法事务回滚不会把B方法的事务回滚
 2)、  rollbackFor指定的异常没有包含抛出的异常
 3)、 以无事务方法调用本类中的事务方法
 4)、 使用了异步--多线程

12、Spring中的设计模式有哪些
工厂模式:Spring使用工厂模式通过 BeanFactory和 ApplicationContext创建 bean 对象
单例模式: Spring 中的 bean 默认都是单例的
代理模式:Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术
模板方法:用来解决代码重复的问题。比如 RestTemplate、jdbcTemplate、 JpaTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如 Spring 中 listener 的实现 ApplicationListener。


13、Spring是怎么解决循环依赖的

循环依赖是指A依赖B,B又依赖A


这就是涉及到SpringIOC容器的三级缓存了

singletonObjects:一级缓存,存放完全初始化好的 Bean 的集合,从这个集合中取出来的 Bean 可以立马返回

earlySingletonObjects:二级缓存,存放创建好但没有初始化属性的 Bean 的集合,它用来解决循环依赖

singletonFactories:三级缓存,存放单实例 Bean 工厂的集合 singletonsCurrentlyInCreation:存放正在被创建的 Bean 的集合

推荐一个帖子:https://www.cnblogs.com/yangxiaohui227/p/10523025.html

14、SpringBean的生命周期


Bean 容器找到配置文件中 Spring Bean 的定义。
Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
如果涉及到一些属性值,利用 set()方法设置一些属性值。
如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入 Bean 的名字。
如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader 对象的实例。
如果 Bean 实现了 BeanFactoryAware 接口,调用 setBeanClassFacotory()方法,传入 ClassLoader 对象的实例。
与上面的类似,如果实现了其他*Aware 接口,就调用相应的方法。
如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行 postProcessBeforeInitialization()方法。
如果 Bean 实现了 InitializingBean 接口,执行 afeterPropertiesSet()方法。
如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcess 对象,执行 postProcessAfterInitialization()方法。
当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy()方法。
当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
总结以上步骤,核心主干主要就是五部分构成:

构造 Bean 对象
设置 Bean 属性
执行初始化方法(如果有就执行)
Bean 调用
销毁 Bean

中间如果实现了一些Aware相关接口的话可以自动执行接口带的实现方法

15、SpringMVC的常用注解有哪些
我们常用的Springmvc注解主要分类下面几大类:

1、用于声明Bean到Springmvc容器:@Controller、@RestController

​ 区别在于后者还可以将返回的集合或对象转换为JSON直接返回

2、设置请求路径:@RequestMapping、@GetMapping、@PostMapping 、@PutMapping、@DeleteMapping

​ 第一个是通用的,可以接收各种类型的请求;后面四个只能直接对应类型的请求

3、接收请求参数:

​ @RequestBody: 接收请求体中的json数据

​ @PathViriable:接收请求路径中的参数

​ @RequestHeader:接收请求头中的参数

​ @RequestParam:一般用于给参数设置默认值或者完成请求参数和controller方法参数的映射

16、SpringMVC如何处理统一异常
SpringMVC的异常处理底层是通过AOP实现的,它的核心思想是将异常处理的代码和业务逻辑代码分离开来

使用它之后,我们在自己的业务代码中不需要在处理异常,有异常直接就上抛到框架中

框架就会将异常交给自定义的全局异常处理器中统一处理

自定义全局异常处理器,会用到两个注解:

@RestControllerAdvice 标注在类上,声明被标注的类是一个用于专门处理异常的类
@ExceptionHandler 标注在异常处理类中的方法上,声明被标注的方法可以处理哪些异常

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值