Spring框架面试常问知识点总结

Spring

一、单例Bean

@Scope

singleton:bean在每个Spring IOC容器中只有一个实例

prototype:一个bean的定义可以有多个实例

线程安全

不是线程安全的,如果在bean中定义了可修改的成员变量,需要考虑线程安全问题,可以使用多例或者加锁来解决

Spring bean并没有可变的状态(比如Service和DAO类),所以在某种程度上来说Spring的单例是线程安全的

AOP

概念:AOP称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和罗技,抽取并封成一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块的耦合度,同时提高了系统的可维护性。事务的底层使用了AOP,AOP底层是动态代理。

常见的AOP使用场景

记录操作日志

缓存处理

Spring中的内置事务处理

Spring中的事务

编程式事务控制

使用TransactionTemplate来实现,对业务代码有侵入性,项目中很少使用

声明式事务控制

声明式事务管理建立在AOP之上,本质是通过AOP功能对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法之前加入一个事物,在执行完目标方法后根据执行情况进行提交或者回滚

二、Spring事务失效的场景

异常捕获处理

@Transactional管理的方法中,多次操作中间存在异常并通过try catch进行了捕获,事务通知只有捕捉到目标抛出的异常才能进行后续的事务回滚处理,如果目标自己处理掉了异常,事务通知无法获悉则会导致失效

解决方法:在catch块内将异常抛出

抛出异常检查

@Transactional管理的方法中,多次操作中间存在检查异常(如:FileNotFountException),由于Spring默认回滚非检查异常,所以事务会失效

解决方法:配置rollbackFor属性,@Transactional(rollbackFor=Exception.class)

非public方法

@Transactional管理的方法中,方法的访问权限不是public,由于Spring为方法创建代理、添加事务通知、前提条件都是该方法是public,所以会导致事务失效

解决方案:改为public方法

三、Bean的生命周期

BeanDefinition

概念:Spring容器在进行实例化时,会将xml配置的的信息封装成一个BeanDefinition对象, Spring根据BeanDifinition来创建Bean对象,里面有很多属性来描述Bean

属性方法

getBeanClassName():获取Bean的类名,用于通过反射创建对象

getInitMethodName():获取初始化方法的名称

getPropertyValues():获取Bean的属性值

getScope():获取作用域

isLazyInit():是否延迟初始化

流程

在这里插入图片描述

四、循环引用

流程

在这里插入图片描述

三级缓存解决循环依赖

概念

一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象

二级缓存:缓存早期的bean对象(生命周期还没走完)

三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的

非代理对象(一级缓存和二级缓存)

在这里插入图片描述

代理对象(三级缓存)

在这里插入图片描述

构造方法循环依赖

无法通过三级缓存的方法来解决循环依赖问题,解决方法是在构造方法上,参数类型前加上注解@Lazy懒加载,需要对象的时候才进行实例化

五、SpringMvc的执行流程

视图阶段

在这里插入图片描述

流程

1、用户发出请求到前端控制器DispatcherServlet

2、DispacherServlet收到请求调用HandlerMapping(处理器映射器)

3、HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器,再一起返回给DispatcherServlet

4、DispatcherServlet调用HandlerAdapter(处理器适配器)

5、HandleAdapter经过适配调用具体的处理器(Handler/Controller)

6、Controller执行完成后返回ModelAndVeiw对象

7、HandleAdapter将Controller执行结果ModelAndView返回给DispatcherServlet

8、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)

9、ViewReslover解析后返回具体Veiw视图

10、DispatcherServlet根据View进行渲染视图

11、DispatcherServlet响应用户

前后端分离阶段(接口开发、异步)

在这里插入图片描述在这里插入图片描述

流程

1、用户发出请求到前端控制器DispatcherServlet

2、DispacherServlet收到请求调用HandlerMapping(处理器映射器)

3、HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器,再一起返回给DispatcherServlet

4、DispatcherServlet调用HandlerAdapter(处理器适配器)

5、HandleAdapter经过适配调用具体的处理器(Handler/Controller)

6、方法上添加了@RequestBody

7、通过HttpMessageConverter返回结果转换为JSON并响应

六、自动配置原理

@SpringBootConfiguration:与@Configuration注解作用相同,用来声明当前类是一个配置类

@ComponentScan:组件扫描注解,默认扫描当前引导类所在包及其子包

@EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解(@Import({AutoConfigurationImportSelector.class})导入自动配置选择器:导入META-INF/spring.factories 内的自动配置类,根据条件注解将类添加到Spring容器中)

常见注解

Spring

@Component、@Controller、@Service、@Repository:使用在类上,用于实例化Bean

@Autowired:使用在字段上,用于根据类型依赖注入

@Qualifier:结合@Autowired一起使用,用于根据名称进行依赖注入

@Scope:标注Bean的作用范围

@Configuration:指定当前类是一个配置类,当创建容器时会从该类上加载注解

@ComponentScan:用于指定Spring在初始化容器时要扫描的包

@Bean:使用在方法上,标注该方法的返回值存储到Spring容器中

@Import:使用@Import导入的类会被Spring加载到IOC容器中

@Aspect、@Befor、@After、@Around、@Pointcut:用于AOP切面编程

SpringMvc

@RequestMapping:用于映射请求路径,可以定义在类上和方法上。用于类上,表示类中的所有方法,都以该地址作为父路径

@RequestBody:注解实现接收http请求的json数据,将json转为java对象

@RequestParam:指定请求参数的名称

@PathViriable:从请求路径中获取请求参数传递给方法的形式参数

@RequestBody:注解实现将controller方法返回对象转为json对象响应给客户端

@RequestHeader:获取指定的请求头数据

@RestController:@Controller+@RespnseBody

SpringBoot

@SpringBootConfiguration:与@Configuration注解作用相同,用来声明当前类是一个配置类

@ComponentScan:组件扫描注解,默认扫描当前引导类所在包及其子包

@EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解(@Import({AutoConfigurationImportSelector.class})导入自动配置选择器:导入META-INF/spring.factories 内的自动配置类,根据条件注解将类添加到Spring容器中)

七、场景模拟

1、Spring框架中的单例bean是线程安全的吗?

不是线程安全的,是这样的。

当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对该单列状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。

Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。

比如:我们通常在项目中使用的Spring bean都是不可可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。

如果你的bean有多种状态的话(比如 View Model对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用由“singleton”变更为“prototype”。

2、什么是AOP

aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般比如可以做为公共日志保存,事务处理等

3、你们项目中有没有使用到AOP

我们当时在后台管理系统中,就是使用aop来记录了系统的操作日志

主要思路是这样的,使用aop中的环绕通知+切点表达式,这个表达式就是要找到要记录日志的方法,然后通过环绕通知的参数获取请求方法的参数,比如类信息、方法信息、注解、请求方式等,获取到这些参数以后,保存到数据库

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

spring实现的事务本质就是aop完成,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

5、Spring中事务失效的场景有哪些

第一个,如果方法上异常捕获处理,自己处理了异常,没有抛出,就会导致事务失效,所以一般处理了异常以后,别忘了跑出去就行了

第二个,如果方法抛出检查异常,如果报错也会导致事务失效,最后在spring事务的注解上,就是@Transactional上配置rollbackFor属性为Exception,这样别管是什么异常,都会回滚事务

第三,我之前还遇到过一个,如果方法上不是public修饰的,也会导致事务失效

嗯,就能想起来那么多

6、Spring的bean的生命周期

首先会通过一个非常重要的类,叫做BeanDefinition获取bean的定义信息,这里面就封装了bean的所有信息,比如,类的全路径,是否是延迟加载,是否是单例等等这些信息

在创建bean的时候,第一步是调用构造函数实例化bean

第二步是bean的依赖注入,比如一些set方法注入,像平时开发用的@Autowire都是这一步完成

第三步是处理Aware接口,如果某一个bean实现了Aware接口就会重写方法执行

第四步是bean的后置处理器BeanPostProcessor,这个是前置处理器

第五步是初始化方法,比如实现了接口InitializingBean或者自定义了方法init-method标签或@PostContruct

第六步是执行了bean的后置处理器BeanPostProcessor,主要是对bean进行增强,有可能在这里产生代理对象

最后一步是销毁bean

7、Spring中的循环引用

循环依赖:循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A

循环依赖在spring中是允许存在,spring框架依据三级缓存已经解决了大部分的循环依赖

①一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象

②二级缓存:缓存早期的bean对象(生命周期还没走完)

③三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的

那具体解决流程清楚吗?

第一,先实例A对象,同时会创建ObjectFactory对象存入三级缓存singletonFactories

第二,A在初始化的时候需要B对象,这个走B的创建的逻辑

第三,B实例化完成,也会创建ObjectFactory对象存入三级缓存singletonFactories

第四,B需要注入A,通过三级缓存中获取ObjectFactory来生成一个A的对象同时存入二级缓存,这个是有两种情况,一个是可能是A的普通对象,另外一个是A的代理对象,都可以让ObjectFactory来生产对应的对象,这也是三级缓存的关键

第五,B通过从通过二级缓存earlySingletonObjects 获得到A的对象后可以正常注入,B创建成功,存入一级缓存singletonObjects

第六,回到A对象初始化,因为B对象已经创建完成,则可以直接注入B,A创建成功存入一次缓存singletonObjects

第七,二级缓存中的临时对象A清除

8、构造方法出现了循环依赖怎么解决?

由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的的依赖注入,可以使用@Lazy懒加载,什么时候需要对象再进行bean对象的创建

9、SpringMVC的执行流程知道嘛

1、用户发送出请求到前端控制器DispatcherServlet,这是一个调度中心

2、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。

3、HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。

4、DispatcherServlet调用HandlerAdapter(处理器适配器)。

5、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。

6、Controller执行完成返回ModelAndView对象。

7、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。

8、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。

9、ViewReslover解析后返回具体View(视图)。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、DispatcherServlet响应用户。

当然现在的开发,基本都是前后端分离的开发的,并没有视图这些,一般都是handler中使用Response直接结果返回

10、Springboot自动配置原理

在Spring Boot项目中的引导类上有一个注解@SpringBootApplication,这个注解是对三个注解进行了封装,分别是:

  • @SpringBootConfiguration

  • @EnableAutoConfiguration

  • @ComponentScan

其中@EnableAutoConfiguration是实现自动化配置的核心注解。

该注解通过@Import注解导入对应的配置选择器。关键的是内部就是读取了该项目和该项目引用的Jar包的的classpath路径下 ”META-INF/spring.factories” 文件中的所配置的类的全类名。

在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。

一般条件判断会有像@ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。

11、Spring 的常见注解有哪些?

第一类是:声明bean,有@Component、@Service、@Repository、@Controller

第二类是:依赖注入相关的,有@Autowired、@Qualifier、@Resourse

第三类是:设置作用域 @Scope

第四类是:spring配置相关的,比如@Configuration,@ComponentScan 和 @Bean

第五类是:跟aop相关做增强的注解 @Aspect,@Before,@After,@Around,@Pointcut

12、SpringMVC常见的注解有哪些?

有@RequestMapping:用于映射请求路径;

@RequestBody:注解实现接收http请求的json数据,将json转换为java对象;

@RequestParam:指定请求参数的名称;

@PathViriable:从请求路径下中获取请求参数(/user/{id}),传递给方法的形式参数;@ResponseBody:注解实现将controller方法返回对象转化为json对象响应给客户端。@RequestHeader:获取指定的请求头数据,还有像@PostMapping、@GetMapping这些。

13、Springboot常见注解有哪些?

Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 :

  • @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能;
  • @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项
  • @ComponentScan:Spring组件扫描
  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值