Spring 面试大纲(持续更新)
2021-12-29 17:35:43 5 举报
AI智能生成
Spring 面试大纲,本人曾靠此面经拿到 35k offer
作者其他创作
大纲/内容
我所理解的 Spring
整个Spring 都是围绕 Bean 这个核心概念来工作的
是否精通 Spring 就看你有没有掌握好 Spring 有哪些扩展点,以及它们的内在机理
通过分析 Spring 给我一个很大的启示就是其这套设计理念其实对我们有很强的借鉴意义,
它通过抽象复杂多变的对象,进一步做规范,然后根据它定义的这套规范设计出一个容器,
容器中构建它们的复杂关系,其实现在有很多情况都可以用这种类似的处理方法。
它通过抽象复杂多变的对象,进一步做规范,然后根据它定义的这套规范设计出一个容器,
容器中构建它们的复杂关系,其实现在有很多情况都可以用这种类似的处理方法。
K8s
计算机系统软件体系结构采用一种层的结构:
“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”
“Any problem in computer science can be solved by anther layer of indirection.”
“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”
“Any problem in computer science can be solved by anther layer of indirection.”
IOC
DIP , DI , IoC 傻傻分不清?
Spring IoC 容器两大接口
BeanFactory
AbstractBeanFactory
DefaultListableBeanFactory
ApplicationContext
AbstractApplication
GenricApplicationContext
AbstractApplicationContext
Spring 注解驱动开发
创建可被发现的bean - @Component
bean name默认为 类名首字母小写
指定bean name @Component("userService")
@ComponentScan
ComponentScan 注解 可以指定扫描包和包含或者排除指定类,可以通过 Class或者注解类型 排除
bean自动装配 - @Autowried
@Autowried 注解 可以用在 构造器,属性,方法上
@Autowired 默认采用 byType 模式自动装配,如果找到多个同类型的,会根据名字匹配。都不匹配,则会报错。
如果遇见多个类型的 Bean ,又不能通过名称自动指定,那么可以使用 @Qualifier() 指定 bean name 。
如果遇见多个类型的 Bean ,又不能通过名称自动指定,那么可以使用 @Qualifier() 指定 bean name 。
BeanPostProcessor 来处理 此注解
@Autowried 、@Inject是如何被解析的?
在 bean后置处理器中 AutowiredAnnotationBeanPostProcessor
@Resource 是如何被解析的?
CommonAnnotationBeanPostProcessor
@Qualifier
可以扩展 此注解,支持分组注入,比如 @LoaderBlance
bean自动装配 - @Resource(java EE 规范)
@Resource 和 Autowired 一样,唯一的区别就是,@Resource 可以自己指定 bean name
// @Resource(name = "studentRepository")
// private StudentRepository studentRepository;
// @Resource(name = "studentRepository")
// private StudentRepository studentRepository;
@Resource 也是 byType
@Value
读取配置文件属性值
@Value("${server.port}")
注意点
不能应用在 static 属性上
@Value +.property 不能注入集合类型
@Value + .yml 可以注入
@PropertySource
注入其他配置文件(.property 或者 .yml)
然后可以使用 @Value() 进行注入
然后可以使用 @Value() 进行注入
@Configuration: 配置Bean
被 @Configuration 标志的类,相当于 spring-bean.xml 文件, 可以在此类中进行 Bean 的定义
需要注意 @Configuration 与 @Import 不能一起使用
工厂读取配置
多配置bean整合
与@Component整合
配置Bean 底层实现原理
Spring在配置Bean中加入了@Configuration注解后,
底层就会通过Cglib 的代理方式,来进行相关Bean 的创建。
底层就会通过Cglib 的代理方式,来进行相关Bean 的创建。
@Bean
结合 @Configuration 一起使用
可以创建复杂对象
FactoryBean 接口也可以创建复杂对象
自定义id值
@Bean("id")
指定作用域
@Bean
@Scop("singleton")
@Scop("singleton")
@Import
使用 Import 导入多个 类作为 Spring IoC 容器的 Bean。
需要注意, 使用 Import 默认是 懒加载 , 即 Lazy 模式,只有在 getBean() 时才会实例化 该 Bean。
@Import 也可以导入其他配置类
Spring 创建Bean 的几种 方式:
创建 Bean 的优先级:@Component及其衍生注解 < @Bean <bean 标签
@Condition
`@Condition` 注解,只有满足条件的 Bean 才会注入到 IoC 容器中
自定义 Condition(根据不同操作系统注入不同的 Bean)
FactoryBean
FactoryBean 是 Spring 提供的用来创建复杂 Spring Bean 的接口。
那什么是复杂对象(Bean)呢?复杂对象(Bean)就是那些不能简单通过构造方法实例化的对象
那什么是复杂对象(Bean)呢?复杂对象(Bean)就是那些不能简单通过构造方法实例化的对象
Aware 系列接口
实现不同的 Aware 接口可以获取不同的 Spring 内置 bean或者功能
每一种 xxxAware 都对应这一个 xxxProcessor 进行处理
而一个 xxxProcessor 可以处理多个 xxxAware 接口
而一个 xxxProcessor 可以处理多个 xxxAware 接口
PostProcessor
BeanPostProcessor
对 Spring 工厂创建的 Bean 进行再加工(Bean 初始化方法调用前后)
BeanFactoryPostProcessor
时机: BeanFactory 初始化后,所有 bean 定义都已保存在 BeanFactory 中,但还未实例化
BeanDefinitionRegistryPostProcessor
时机: 所有的 BeanDefinition 被加载之后,所有的 Bean 还未实例化
> BeanDefinitionRegistryPostProcessor 优先于 BeanFactoryPostProcessor 执行
> BeanDefinitionRegistryPostProcessor 优先于 BeanFactoryPostProcessor 执行
AnnotationConfigUtils
需要注意的是:所有的 BeanPostProcessor 也会被当做Bean注入到 Spring 容器中
org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
ApplicationListener
Spring 中的事件机制使用了观察者模式,
1. IoC 容器启动时,扫描所有的 Listener 组件,每次发布一个 AppilcationEvent 就 循环这些 Listener 回调方法。
1. IoC 容器启动时,扫描所有的 Listener 组件,每次发布一个 AppilcationEvent 就 循环这些 Listener 回调方法。
Spring Profile
多环境配置
Spring YAML
YAML 与Spring 整合
Spring Bean
bean的生命周期
实例化 Instantiation
属性赋值 Populate
初始化 Initialization
销毁 Destruction
实例化和初始化前后都快可以进行微调
属性赋值 Populate
初始化 Initialization
销毁 Destruction
实例化和初始化前后都快可以进行微调
Spring 容器启动过程
Spring 如何解决循环依赖?
首先搞清楚什么是Spring 的 Bean 创建循环依赖?
比如有两个类,A和B,A中有个属性为 b,B中有个属性为 a,
这样在Spring 的IoC 容器为我们注入依赖的时候,就会产生所谓的循环依赖。
这样在Spring 的IoC 容器为我们注入依赖的时候,就会产生所谓的循环依赖。
如何解决?
首先抛弃掉Spring,如果使我们自己来创建这两个对象,怎么解决呢?
很容易: 把 A ,B都先实例化出来,再set不就好了。
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
很容易: 把 A ,B都先实例化出来,再set不就好了。
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
Spring 解决循环依赖的思路也是类似的!
(三级缓存)(三个Map)
(三级缓存)(三个Map)
Spring内部维护了三个Map,也就是我们通常说的三级缓存。
在Spring的DefaultSingletonBeanRegistry类中,你会赫然发现类上方挂着这三个Map:
singletonObjects 它是我们最熟悉的朋友,俗称“单例池”“容器”,缓存创建完成单例Bean的地方。
singletonFactories 映射创建Bean的原始工厂
earlySingletonObjects 映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,甚至还不能称之为“Bean”,只是一个Instance.
在Spring的DefaultSingletonBeanRegistry类中,你会赫然发现类上方挂着这三个Map:
singletonObjects 它是我们最熟悉的朋友,俗称“单例池”“容器”,缓存创建完成单例Bean的地方。
singletonFactories 映射创建Bean的原始工厂
earlySingletonObjects 映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,甚至还不能称之为“Bean”,只是一个Instance.
一句话解释:Spring 在创建Bean 的时候,如果发现自己还有其它依赖,就把自己放在 一个早期Bean 池里面,即earlySingletonObjects 中
Spring 循环依赖分为三种:
构造器
Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中。
因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;
而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;
而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
setter循环依赖(单例)
Bean 实例化图
对于 setter 方式注入,Spring 是先将 Bean 实例化后再设置属性的, Spring 先将这个 实例化的 Bean 放在一个早期的 Bean 引用池中,当需要 setter 设置属性时,就从这个 早期引用池中寻找赋值. --> 参考: DefaultSingletonBeanRegistry.java
setter 循环依赖(原型)
不支持循环依赖,因为对于 原型的 Bean,Spring 无法进行早期 Bean 的缓存,每次获取的都是一个新对象,无法解决循环依赖.
Spring 不支持构造器循环依赖!
极客时间
Spring Bean 相关
Bean 配置元信息
BeanDefinition
BeanDefinition
主要分为以下几类
GenericBeanDefiniion:通用 BeanDefinition
RootBeanDefinition:无Parent的BeanDefinitio或者合并后的BeanDefinition
AnnotatedBeanDefinition:注解标注的BeanDefinition
基于java注解装载 Spring bean 配置元信息
@Component 及其衍生注解
被@Component 标注的类,会在Spring 开启类路径扫描时,自动装配为 Spring 的Bean。
ClassPathBeanDefinitionScanner:Bean Definition 扫描器,把被@Component及其衍生注解标注的类扫描为 Bean Definition 并注册到 BeanFactory 中。
扫描动作是由 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 完成触发的。
可以自定义这个BeanFactoryPostProcessor 在这里面手动注册 BeanDefinition
可以自定义这个BeanFactoryPostProcessor 在这里面手动注册 BeanDefinition
Spring Resource 相关
引入动机?
Spring 校验:Validated
Spring 放弃了自己的校验实现,整合了 hibernate-calidator 校验框架
Spring Validation 最佳时间及其实现原理,参数校验没那么简单?
一图看懂 @Valid 和 @Validated 注解
Spring 事件:ApplicationEvent -> ApplicationListener
ApplicationEvent 继承了 java.util.EventObject:
ApplicationContextEvent
ApplicationContextEvent
事件监听器: ApplicationListener:监听 ApplicationEvent 类型事件
监听器的两种实现方式
接口方式: ApplicationListener
注解方式:@EventListener
事件发布器:
ApplicationEventPublisher(事件发布)
ApplicationEcentMulticaster(事件广播)
ApplicationEventPublisher(事件发布)
ApplicationEcentMulticaster(事件广播)
获取ApplicationEventPublisher 的方式
一: ApplicationEventPublisherAware 接口回调注入
二:依赖注入:ApplicationPublisher
三:使用 ApplicationCopntext 发布事件
获取 ApplicationEventMulticaster 的方式:
依赖查找
依赖注入
自定义 Spring事件
分为三步:
1. 自定义事件:扩展ApplicationEvent
2. 自定义事件监听器(或者使用@EventListener):ApplicationEventListener,注册到ApplicationContext 容器中。
3.发布自定义事件:使用ApplicationContext,或者 实现 ApplicationEventPublisherAware 接口 获取 ApplicationEventPublisher
1. 自定义事件:扩展ApplicationEvent
2. 自定义事件监听器(或者使用@EventListener):ApplicationEventListener,注册到ApplicationContext 容器中。
3.发布自定义事件:使用ApplicationContext,或者 实现 ApplicationEventPublisherAware 接口 获取 ApplicationEventPublisher
Demo
广播事件
ApplicationEventMulticaster
广播事件,可以添加监听器,可以向所有添加的监听器进行广播;
类似 发布订阅模式
类似 发布订阅模式
异步事件
方法一
方法二:使用注解:@Async
SpringBoot 中的事件
Spring Cloud 中的事件
Spring 同步事件和异步事件的使用场景?
答
@EventListener 的工作原理?
基于BeanPostProcesor
。。。
BeanFactory相关
BeanFactory 和 AppilcationContext 谁才是 Spring 的 IoC 容器?
BeanFactory 提供了一个配置框架的基本功能,可以获取任意 object 的工厂,
ApplicationContext 提供了一些更加高级的功能。
比如与 AOP 集成,国际化,事件处理,注解,Environment以及与 Web 整合。
ApplicationContext 提供了一些更加高级的功能。
比如与 AOP 集成,国际化,事件处理,注解,Environment以及与 Web 整合。
AppilcationContext 是 BeanFactory 的子类,但是是内部持有了一个 DefaultListenerableBeanFactory 对象
来代理实现 BeanFactory 的所有方法。可以认为Application 是Beanfactory 的超集。
来代理实现 BeanFactory 的所有方法。可以认为Application 是Beanfactory 的超集。
GenericApplicationContext
这是 ApplicationContext 的实现类,是很多其他具体 ApllicationContext 的实现类。
BeanFactory和FactoryBean?
答:BeanFactory 是IoC的底层容器;
FactoryBean 是创建Bean的一种方式,帮助实现复杂的初始化逻辑。
FactoryBean 是创建Bean的一种方式,帮助实现复杂的初始化逻辑。
Spring IoC 容器生命周期:IoC容器启动停止过程发生了什么?
BeanFactory 是怎样处理 Bean 的生命周期的?
BeanFactory 是怎样处理 Bean 的生命周期的?
refresh()方法
第一部分: 准备 Beanfactory
第二部分: 准备 Bean
第三部分: 国际化,监听器等
第一部分: 准备 Beanfactory
第二部分: 准备 Bean
第三部分: 国际化,监听器等
prepareRefresh()
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
创建BeanFactory实例的工厂
prepareBeanFactory(beanFactory); 准备工厂
往 BeanFactory 实例中放置一些内建的Bean或者非Bean对象
配置工厂的标准上下文特征,例如上下文的ClassLoader和后置处理器。
postProcessBeanFactory(beanFactory);
扩展点:子类实现
invokeBeanFactoryPostProcessors(beanFactory);
实例化并调用所有已注册的BeanFactoryPostProcessor
registerBeanPostProcessors(beanFactory);
扩展点:实例化并注册所有BeanPostProcessor Bean
在Bean实例化后做一些调整
在Bean实例化后做一些调整
initMessageSource();
国际化
initApplicationEventMulticaster();
onRefresh();
容器和Bean都已经调整完毕
registerListeners();
扩展点:注册监听器Listener
finishBeanFactoryInitialization(beanFactory);
完成BeanFactory 的实例化,后的一些操作
finishRefresh();
发布相应事件 Event,告知监听器Listener
1. Spring Bean 元信息创建-- BeanDefinition
什么是BeanDefinition?
BeanDefinition 是Spring 中定义 Bean 的配置元信息接口。包含 Bean 的类名即父类信息,作用域,生命周期回调,其它Bean依赖等。
BeanDefinitionRegistry#registry(BeanDefinition beanDefinition)
BeanDefinition配置阶段
BeanDefinition解析阶段
BeanDefinition注册阶段
BeanDefinitionRegister
BeanDefinition 合并
2. Spring Bean 创建
Bean Class 类加载阶段
String -》 Class
Bean 实例化阶段
实例化前:回调InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation()方法;
让我们有机会自己实例化对象。
让我们有机会自己实例化对象。
实例化后:回调 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation() 方法;
让我们在填充Bean 之前回调。
让我们在填充Bean 之前回调。
3. Bean实例化后进行属性赋值
属性赋值前回调:InstantitationAwareBeanPostProcessor#postProcessProperties
4. Aware 接口回调
执行顺序
Aware 的处理是在 BeanPostProcessor 中处理的:ApplicationContextAwareProcessor
5. Spring Bean 初始化
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
Spring Bean 初始化完成回调:
SmartInitializingSingleton
SmartInitializingSingleton
6. Spring Bean 销毁
在 BeanPostProcessor 中处理
7. Spring Bean 垃圾收集
1.关闭Spring容器(应用上下文)
2.执行GC
Spring Bean 覆盖的 finalize() 方法被回调
BeanPostProcessor 的使用场景有哪些?
答:BeanPostProcessor 提供了 Spring Bean 初始化前和初始化后的生命周期回调;在 Spring 中,有很多特性都是基于 BeanPostProcessor 来实现的:
应用一:并且允许对关心的Bean 进行扩展,替换等,比如:Spring AOP 的实现(AnnotationAwareAspectJAutoProxyCreator);
应用二:并且,ApplicationContext 相关的系列 Aware 接口的回调也是基于 BeanPostProcessor 实现的。(ApplicationContextAwareProcessor);
应用三:@Autowried,@Resource,@Inject 等自动装配的注解支持也是基于 BeanpoatProcessor(AutowiredAnnotationBeanPostProcessor)。
应用一:并且允许对关心的Bean 进行扩展,替换等,比如:Spring AOP 的实现(AnnotationAwareAspectJAutoProxyCreator);
应用二:并且,ApplicationContext 相关的系列 Aware 接口的回调也是基于 BeanPostProcessor 实现的。(ApplicationContextAwareProcessor);
应用三:@Autowried,@Resource,@Inject 等自动装配的注解支持也是基于 BeanpoatProcessor(AutowiredAnnotationBeanPostProcessor)。
BeanFactoryPostProcessor和BeanPostProcessor的区别?
答:BeanFactoryPostProcessor 是Spring BeanFactory(ConfigurableListableBeanFactory) 的后置处理器。
主要用来扩展 BeanFactory 或者通过 BeanFactory 进行依赖查找和依赖注入。
需要注意的是:BeanFactoryPostProcessor 必须由 Spring ApplicationContext 执行,BeanFactory 无法与其直接交互。
而 BeanPostProcessor 的回调实际上是由 BeanFactry (DefaultListableBeanFactory)来执行的。
主要用来扩展 BeanFactory 或者通过 BeanFactory 进行依赖查找和依赖注入。
需要注意的是:BeanFactoryPostProcessor 必须由 Spring ApplicationContext 执行,BeanFactory 无法与其直接交互。
而 BeanPostProcessor 的回调实际上是由 BeanFactry (DefaultListableBeanFactory)来执行的。
BeanFactoryPostProcessor 的一个典型应用场景:扫描 @Component及其衍生注解,注册为Spring Bean
依赖查找和依赖注入
DL 和 DI
DL 和 DI
依赖注入有哪几种类型?
Setter 方法
可选的依赖
构造器
少依赖,强制依赖
字段
开发方便
方法
@Bean
接口回调注入
xxxAware
SpringIoC依赖来源?-- Spring容器管理的和游离的对象
Spring BeanDefinition 作为依赖来源
@Bean,@Autowried ,@EventListener等等
单例对象作为依赖来源
Environment,MessageSource,ApplicationEventMulticaster 等等
非Spring容器管理对象作为依赖来源
游离的几个对象
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
外部化配置作为依赖来源
@Value
Spring依赖注入和依赖查找的区别?
注入和查找的依赖来源是否相同?
注入和查找的依赖来源是否相同?
依赖注入的来源比依赖查找多一项,那就是游离对象,即使用 registerResolvableDependency()注入容器的对象,
注意:这些对象是不能通过依赖查找(getBean()方法)获取的。默认会帮我们注入四种
注意:这些对象是不能通过依赖查找(getBean()方法)获取的。默认会帮我们注入四种
Spring容器管理的和游离的对象
不同:依赖查找的来源仅限于 Spring BeanDefinition 以及单例对象;
而依赖注入的来源还包括 Resolvable Dependency 以及 @Value 所标注的外部化配置。
而依赖注入的来源还包括 Resolvable Dependency 以及 @Value 所标注的外部化配置。
依赖处理
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
DependencyDescriptor descriptor 依赖描述符,描述当前要解析的 bean 的一些信息
@Autowried 是如何被解析的?
在 bean后置处理器中 AutowiredAnnotationBeanPostProcessor 判断是有被 @Autowried 标注,是的话构造 依赖描述符,等信息,调用 DefaultListableBeanFactory#resolveDependency()方法进行依赖处理。
BeanFactory.getBean() 操作是否线程安全?
是线程安全的,操作过程会增加一个互斥锁。
很好理解,因为有些Bean是延迟初始化的,或者非单例的。
很好理解,因为有些Bean是延迟初始化的,或者非单例的。
Bean 作用域
singleon
prototype
request
session
application
prototype
request
session
application
结论一:
Singleton Bean 无论依赖查找还是注入,均为同一个对象。
Prototype Bean 无论依赖查找还是注入,均为新生成的对象。
Prototype Bean 无论依赖查找还是注入,均为新生成的对象。
结论二:
无论是 Singleton 还是 Prototype 均会执行Bean初始化方法回调,不过只有 Singleton 只会执行销毁。
singleton Bean 是否在整个应用中是惟一的?
否,Singleton Bean 仅在当前Spring IoC 容器(BeanFactory)中是单例对象。一个应用可能包含多个 BeanFactory
aoolication Bean 是否可以被其他方案替代?
可以的,实际上 application Bean 与 singleton Bean 没有本质区别。
Sring 注解编程
@ComponentScan
工作原理
注解别名、元标注
显示别名
@AliasFor,注解继承多个元注解,显示指定覆盖哪一个元注解的属性
隐式别名
注解继承,覆盖元注解中的属性
@EnbaleXXX 模块驱动
实现方式
第一步:新建一个注解 @EnableXXX
第二步:@EnableXXX 上打上元注解 @Import()
第三步:利用@Import()注解的作用导入其他配置Bean,或者普通 Bean;
或者可以利用 @ImportSelector()注解进行逻辑条件导入
或者可以利用 @ImportSelector()注解进行逻辑条件导入
@Conditional 条件注解
实现原理
Spring Environment 抽象
Spring 应用上下文生命周期
AbstractApplicationContext#refresh
AbstractApplicationContext#refresh
上下文创建前准备阶段:
prepareRefresh()
prepareRefresh()
启动时间 - startipDate
this.startupDate = System.currentTimeMillis();
状态标识
this.closed.set(false);
this.active.set(true);
this.active.set(true);
初始化 propertySources
// Initialize any placeholder property sources in the context environment.
initPropertySources();
initPropertySources();
校验 Environment 中必须属性
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
初始化事件监听器集合
(早期事件)
(早期事件)
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
BeanFactory创建阶段:
beanFactory = obtainFreshBeanFactory();
beanFactory = obtainFreshBeanFactory();
创建一个 DefaultListableBeanFactory 的实例
BeanFactory 准备阶段:
prepareBeanFactory(beanFactory);
prepareBeanFactory(beanFactory);
BeanFactory 后置处理阶段:
postProcessBeanFactory(beanFactory);
postProcessBeanFactory(beanFactory);
AOP
AOP,Spring AOP ,Aspectj,CGLIB 傻傻分不清?
Spring 实现 AOP 的两种方式
JDK 动态代理
基于接口
Cglib 动态代理
基于父子继承
Spring 是如何为我们创建代理对象的?
BeanPostProcessor
Spring AOP 的底层实现
模拟实现 Spring 借助 BeanPostProcessor 实现动态代理
Spring 基于注解(Aspectj)的AOP编程
启用 Spring AOP: @EnableAspectJAutoProxy
默认是使用 JDk 动态代理
坑:代理对象内的方法相互调用
Spring 事务
四个特点(ACID)
A:原子性
C:一致性
I:持久性
D:隔离性
如何控制事务
Connection.setAutoCommit(false);
Connection.commit();
Connection.rollback();
Connection.commit();
Connection.rollback();
Spring控制事务的开发:AOP
给DataSourceTransaction注入DataSource依赖
基于注解的事务使用:引入依赖 spring-tx
@Transactional
加在方法上
加在类上
Spring 中的事务属性
什么是事务属性?描述事务特征的一系类值
隔离属性(Isolation)
描述了事务解决并发问题的特征
两个事务同事访问同一条数据
并发事务会产生那些问题?
脏读/读未提交
一个事务读取了另一个事务没有提交的数据。
大部分情况下都不允许脏读的情况出现
解决方案:
@Transactional(isolation = Isolation.READ_COMMITTED)
意思就是读: 可以读取已提交的数据
@Transactional(isolation = Isolation.READ_COMMITTED)
意思就是读: 可以读取已提交的数据
不可重复读
一个事务中,多次读取相同(一条)的数据,但读取结果不一样。
解决方案:
@Transactional(isolation = Isolation.REPEATABLE_READ)
意思就是 可重复度
@Transactional(isolation = Isolation.REPEATABLE_READ)
意思就是 可重复度
MySQL 默认隔离级别:可重复读
幻读
一个事物中,多次多整表进行统计查询,结果不一致。
解决方案:
@Transactional(isolation = Isolation.SERIALIZABLE)
意思就是,事务要阻塞执行
@Transactional(isolation = Isolation.SERIALIZABLE)
意思就是,事务要阻塞执行
并发事务问题如何解决?
通过隔离属性解决,
隔离属性中设置不同的值,解决并发事务遇到的问题
隔离属性中设置不同的值,解决并发事务遇到的问题
隔离属性在实战中的建议
最好使用默认值
MySQL:可重复读
如果遇到并发事务问题
现实中推荐使用 乐观锁
传播属性(propagation)
为了解决一个事务方法调用另一个事务方法的事务嵌套问题
喜马拉雅面试
为了解决一个事务方法调用另一个事务方法的事务嵌套问题
喜马拉雅面试
事务嵌套
@Transactional(propagation = Propagation.REQUIRED)
外部不存在事务,开启新事物;存在事务,就加入。
外部不存在事务,开启新事物;存在事务,就加入。
增删改
@Transactional(propagation = Propagation.SUPPORTS)
外部不存在事务,不开启新事物;存在事务,就加入。
外部不存在事务,不开启新事物;存在事务,就加入。
查
其他的及其不常用。
建议使用默认值。
Propagation.REQUIRED(传播_需要)
只读属性(readOnly)
针对只进行查询的事务,加上只读属性,会提高效率。
@Transactional(readOnly = true)
默认值为 false
默认值为 false
超时属性(timeout)
@Transactional(timeout = 5)
默认值为-1,表示使用数据库默认事务等待超时时间。
默认值为-1,表示使用数据库默认事务等待超时时间。
数据库默认的等待时间是 50 s
当前事务访问其他加锁事务,必须等待的时候,可以指定一个等待时间。
超过等待时间就会抛出异常:TransactionTimedOutException:Transaction timed out
超过等待时间就会抛出异常:TransactionTimedOutException:Transaction timed out
建议使用默认值
异常属性
@Transactional(rollbackFor = RuntimeException.class)
默认只对 RuntimeException 异常及其子类进行异常回滚。
默认只对 RuntimeException 异常及其子类进行异常回滚。
Exception 和 RuntimeException 区别
建议使用默认值
SpringMVC
SpringMVC 与 Spring 如何整合?
问题:Web 开发中如何创建工厂?
Web 环境下,Spring工厂为: WebApplicationContext/WebXmlApplicationContext
问题:那么如何保存Web工厂并且保证工厂唯一?
servlvlet知识点回顾:
四大作用域
application(对应 ServletContext 对象)
全局作用范围,整个应用程序共享,生命周期为:应用程序启动到停止。
非常适合用来存储 Spring 的Web工厂。
session
request(对应 HttpServletRequest/ServletRequest对象)
page(对应 this)
在 ServletContext 对象创建的时候把工厂存储在Servlet 的全局作用域: application(ServletContext 对象中)
问题:ServletContext 对象何时创建?
使用 ServletContextListener 在监听到 ServletContext 创建后,就创建 Web工厂并且往里面存放 Web工厂对象
问题:SpringMVC 中到底如何整合的?
SpringWebMVC 中有一个类: ContextLoaderListener 为我们做了上面的所有事情:
1.创建工厂
把工厂存放在 ServletContext 中
SpringMVC 工作流程?
说一说 SpringBoot 自动装配原理?
SpringBoot 定义了一套接口规范: SpringBoot 在启动时,会扫描外部引用 Jar 包中的 Resource 下的 META_INF/spring.factories 文件,
将文件中的类型信息加载器到 Spring 容器.
我理解的自动装配就是: 引入特定的 JAR 之后,通过注解,或者简单的配置,就能在 SpringBoot 的帮助下实现某些功能.
将文件中的类型信息加载器到 Spring 容器.
我理解的自动装配就是: 引入特定的 JAR 之后,通过注解,或者简单的配置,就能在 SpringBoot 的帮助下实现某些功能.
Spring Boot 通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖
说一说 SpringBoot 如何与 Tomcat 整合的?
Tomcat 作为一个软件一个 Servlet 容器,是可以直接 new 出来的.
0 条评论
下一页