Spring框架相关问题
文章目录
- 1 Spring MVC 执行流程
- 2 Spring 框架中用到的设计模式
- 3 Spring 事务、隔离级别
- 4 @SpringBootApplication 做了哪些事
- 5 Spring Boot 自动装配原理
- 6 Spring 容器:BeanFactory & ApplicationContext
- 7 依赖注入的两种方式
- 8 单例 Bean 是线程安全的吗
- 9 AOP 通知的执行顺序
- 10 依赖注入的四个注解
1 Spring MVC 执行流程
- 客户端(浏览器)发送请求,直接请求到
DispatcherServlet
。 DispatcherServlet
根据请求信息调用HandlerMapping
,解析请求对应的Handler
。- 解析到对应的
Handler
(也就是Controller
)后,开始由HandlerAdapter
适配器处理。 HandlerAdapter
会根据Handler
来调用真正的处理器开处理请求,并处理相应的业务逻辑。- 处理器处理完业务后,会返回一个
ModelAndView
对象,Model 是返回的数据对象,View 是逻辑上的视图。 ViewResolver
会根据逻辑 View 查找实际的 View。DispaterServlet
进行视图渲染。- 把 View 返回给请求者(浏览器)。
2 Spring 框架中用到的设计模式
参考:Spring 中的设计模式
- 工厂模式
Spring 通过BeanFactory
、ApplicationContext
创建 Bean 对象 - 单例模式
Bean 默认都是单例的 - 代理模式
AOP 功能的实现基于代理模式 - 模板模式
xxxTemplate(例如RestTemplate
等)使用了模板模式 - 适配器模式
Spring AOP 的增强或通知(Advice,例如@ControllerAdvice
)使用到了适配器模式;Spring MVC 中用到了适配器模式适配 Controller
3 Spring 事务、隔离级别
- 一般使用
@Transactional
注解方式实现,只能应用到 public 方法上,否则不生效 - 事务传播:解决业务层方法之间互相调用的事务问题
传播行为 | 解释 |
---|---|
PROPAGATION_REQUIRED
|
@Transactional注解 默认使用。如果当前存在事务,则加入该事务(变成了同一事务,只要一个方法回滚,整个事务均回滚);如果当前没有事务,则创建一个新的事务
|
PROPAGATION_REQUIRES_NEW
|
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,会新开启自己的事务,且开启的事务相互独立,互不干扰 |
PROPAGATION_NESTED
|
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则等价于 PROPAGATION_REQUIRED
|
PROPAGATION_MANDATORY
|
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常 |
- 隔离级别:类似于 MySQL
隔离级别 | 解释 |
---|---|
ISOLATION_DEFAULT
|
默认的隔离级别,MySQL 默认采用的 REPEATABLE_READ 隔离级别,Oracle 默认采用的 READ_COMMITTED 隔离级别
|
ISOLATION_READ_UNCOMMITTED
|
允许读取尚未提交的数据变更,可能会导致 脏读、幻读或不可重复读 |
ISOLATION_READ_COMMITTED
|
允许读取并发事务已提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生 |
ISOLATION_REPEATABLE_READ
|
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生 |
ISOLATION_SERIALIZABLE
|
所有事务依次执行,这样事务之间就不可能产生干扰,可以防止脏读、不可重复读以及幻读 |
@Transactional(rollbackFor = MyException.class)
注解
如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚在
@Transactional
注解中如果不配置rollbackFor
属性,那么事务只会在遇到RuntimeException
的时候才会回滚,加上rollbackFor=Exception.class
,可以让事务在遇到自定义的非运行时异常时也回滚
4 @SpringBootApplication 做了哪些事
@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
@EnableAutoConfiguration
:启用 SpringBoot 的自动配置机制@ComponentScan
: 扫描被@Component (@Service,@Controller)
注解的 bean,注解默认会扫描该类所在的包下所有的类@Configuration
:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类
5 Spring Boot 自动装配原理
自动装配可以简单理解为:通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能
@SpringBootApplication
->@EnableAutoConfiguration
->AutoConfigurationImportSelector
AutoConfigurationImportSelector
实现了ImportSelector
接口中的selectImports
方法,该方法主要用于获取所有符合条件的类的全限定类名(返回 String 数组,一系列的 “xxxAutoConfiguration”),这些类需要被加载到 IoC 容器中
private static final String[] NO_IMPORTS = new String[0];public String[] selectImports(AnnotationMetadata annotationMetadata) {// <1>.判断自动装配开关是否打开if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;} else {//<2>.获取所有需要装配的beanAutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); // 下图详细说明return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
}
下图中的红色字体“自动配置类名”即为 xxxAutoConfiguration 类
- 所有 Spring Boot Starter 下的 META-INF/spring.factories 都会被读取到。
XXXAutoConfiguration
类的作用就是按需加载组件
- 启动应用时,不同的 Stater 的 spring.factories 的配置很多,每次启动不会全部加载。只有自动配置类或其中的方法上的
@ConditionalOnXXX
中的所有条件都满足才会生效
@Configuration
// 检查相关的类是否存在,存在才会加载
@ConditionalOnClass({EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class})
@ConditionalOnProperty(prefix = "spring.aop", name = {"auto"}, havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {// ...@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = {"proxy-target-class"}, havingValue = "true", matchIfMissing = true)public static class CglibAutoProxyConfiguration {public CglibAutoProxyConfiguration() {}}// ...
}
6 Spring 容器:BeanFactory & ApplicationContext
BeanFactory
和ApplicationContext
是 Spring 的两大核心接口,都可以当做 Spring 的容器,ApplicationContext
是BeanFactory
的子接口BeanFactroy
采用的是 延迟加载 形式来注入 Bean 的,即只有在使用到某个 Bean 时(调用getBean()
),才对该 Bean 进行实例化- 这样导致不能发现一些存在的 Spring 的配置问题:如果Bean的某一个属性没有注入,
BeanFacotry
加载后,直至第一次使用调用getBean
方法才会抛出异常 - 是一种低级的容器,类似于一个
HashMap
,Key 是 BeanName,Value 是 Bean 实例,通常只提供注册(put),获取(get)这两个功能
- 这样导致不能发现一些存在的 Spring 的配置问题:如果Bean的某一个属性没有注入,
ApplicationContext
在容器启动时,一次性创建了所有的 Bean(把创建资源的过程放在服务器启动时)。这样在容器启动时就可以发现 Spring 中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext
启动后预载入所有的单实例Bean,通过预载入单实例 Bean,确保当需要的时候就不用等待
7 依赖注入的两种方式
使用 setter 方法
- 容器通过调用无参构造器或无参static工厂方法实例化 Bean 之后,调用该 Bean 的 setter 方法
- 用于实现可选依赖,适合设置少量属性使用有参构造器
- 构造器依赖注入通过容器触发一个类的构造器来实现的
- 用于实现强制依赖,适合设置大量属性
8 单例 Bean 是线程安全的吗
- 不是,Spring 框架并没有对单例 Bean 进行多线程的封装处理
- 大部分时候 Bean 是无状态的(比如 dao ,无状态即不会保存数据),所以大部分 Bean 是线程安全的
- 如果 Bean 有状态的话,需要开发者保证线程安全,最简单的就是改变 Bean 的作用域,把
singleton
变更为prototype
,这样请求 Bean 相当于new Bean()
,就可以保证线程安全了
9 AOP 通知的执行顺序
@Component(value = "enhanceClass")
@Aspect
public class EnhanceClass {@Before(value = "execution(* pojo.MyClass.add(..))")public void before() {System.out.println("前置通知");}@AfterReturning(value = "execution(* pojo.MyClass.add(..))")public void afterReturning() {System.out.println("后置通知,正常返回时才执行");}@After(value = "execution(* pojo.MyClass.add(..))")public void after() {System.out.println("最终通知,无论是否正常返回都执行");}@AfterThrowing(value = "execution(* pojo.MyClass.add(..))")public void afterThrowing() {System.out.println("异常通知");}@Around(value = "execution(* pojo.MyClass.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕通知:前");proceedingJoinPoint.proceed();System.out.println("环绕通知:后");}
}- 无异常时:
1. around before advice
2. before advice
3. target method
4. around after advice
5. after advice
6. afterReturning advice- 有异常时:
1. around before advice
2. before advice
3. target method 执行
4. around after advice
5. after advice
6. afterThrowing advice
7. 异常发生
10 依赖注入的四个注解
注解 | 作用 | 范围 |
---|---|---|
@Autowired
|
按类型自动装配 | 构造方法、成员变量、Setter 方法 |
@Qualifier
|
按名称自动装配,需要和 @Autowired 搭配使用
|
成员变量、Setter 方法 |
@Resource
|
按名称或类型自动装配;未指定规则时,默认先按名称装配,找不到满足要求的 bean,再按类型装配 | 成员变量、Setter 方法 |
@Value
|
注入 int / float / String 等基本数据类型 | 成员变量、Setter 方法 |
Spring框架相关问题相关推荐
- Spring框架入门
目录 Spring框架概述 1.Spring框架组成 2.使用spring有什么好处 3.为什么使用spring框架 4.Spring快速入门 4.1Spring IoC底层实现原理 4.2下载Spr ...
- Spring框架快速入门
目录 什么是Spring? 为什么学习Spring? Spring的快速入门 Spring的版本 IOC概述 什么是IOC? Spring的IoC入门 下载Spring的开发包 创建web项目,引入S ...
- Spring入门第一讲——Spring框架的快速入门
Spring的概述 什么是Spring? 我们可以从度娘上看到这样有关Spring的介绍: 说得更加详细一点,Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架, ...
- 手写简易版Spring框架(七):定义标记类型接口Aware,实现感知容器相关的信息
文末有惊喜 目标 目前已实现的 Spring 框架,在 Bean 操作上能提供出的能力,包括:Bean 对象的定义和注册,以及在操作 Bean 对象过程中执行的,BeanFactoryPostProc ...
- Spring框架系列之AOP思想
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.AOP概述 (1).什么是 AOP AOP 为 Aspect Oriented Progra ...
- spring 全局变量_[Spring]-Spring框架-02-IOC容器
Spring框架 IOC容器 理解IOC容器和DI依赖注入 IOC容器 Inverser Of Control反转控制 就是把原来在程序中创建HelloService对象的控制权限交给Spring管理 ...
- 阿里三面让我现场改造Spring框架,明天带他去爬山!
作为一个Java程序员,提到开源框架,Spring无疑是绕不过去的门槛,相信大家对它都不陌生,或多或少都用过. 但是如果谈到改造Spring框架,实现它的自定义扩展,以及大厂面试必问的源码,很多人就会 ...
- spring学习12 -Spring 框架模块以及面试常见问题注解等
以下为spring常见面试问题: 1.Spring 框架中都用到了哪些设计模式? Spring框架中使用到了大量的设计模式,下面列举了比较有代表性的: 代理模式-在AOP和remoting中被用的比较 ...
- Spring 系列: Spring 框架简介
Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架. 在这篇由三部 ...
最新文章
- 困扰人工智能50多年的常识问题,是否迎来“破局”?
- 【控制】《鲁棒控制-线性矩阵不等式处理方法》-俞立老师-第1章-引言
- 开启php,php开启openssl的方法
- python与rpc服务
- windows下快速启动或关闭系统服务方法
- 世界上最欢乐的职业,可能就是蹦极的工作人员了!
- linux延时与定时操作
- Windows/Android/IOS平台如何在Unity3d播放RTSP/RTMP流
- [Thinking]从赢在中国,思考博客园的商业化
- java简单ai聊天_一个hello/hi的简单的网络聊天程序——JAVA
- 划分子网后的三级结构
- python新式类c3算法_python中的MRO和C3算法
- IoT:加密与安全:几种常用安全加密算法原理与用途解析
- Android JSON 数据解析 之原生 API
- 多核时代不宜再用 x86 的 RDTSC 指令测试指令周期和时间
- python 扫描枪_获取键盘输入或者USB扫描枪数据
- 部落战魂找不到服务器,部落战魂官方版
- 【ECLIPSE 二】eclipse java web 版本修改问题 3.0-2.5
- 《风暴英雄》游戏体验
- 操作系统实验一到实验九合集(哈工大李治军)
热门文章
- Asp.net 面向接口可扩展框架之核心容器
- byte java byte_详解java中的byte类型
- Failed:(13: Permission denied)导致访问浏览器出现Nginx 500 Internal Server Error
- C语言试题四十八之该函数可以统计一个长度为2的字符串在另一个字符串中出现的次数。
- 「零门槛多语言 Python/C/C# 通用思想学习系列」第一篇:经典HelloWorld
- 世界上最震撼的地质景观,你认识多少?
- 高糊马赛克秒变高清,表情帝:这还是我吗?
- 人体的血管连起来竟能绕地球两圈!?| 今日最佳
- 教师节,老师们最大的愿望竟然是。。 | 今日最佳
- 豆瓣最高评分8.9!让你拥有“多样性思维”