Spring 事务、异步和循环依赖有什么关系?
前言在循环依赖中有一种循环依赖,就是自注入:自己依赖自己。
事务的自注入在 Spring 自调用事务失效,你是怎么解决的? 有小伙伴提出可以自己注入自己来解决事务失效。
具体使用方式如下:
@Slf4j@Servicepublic class OrderBizServiceImpl implements OrderBizService { // 注入自己 @Autowired private OrderBizService orderBizService; @Override public void callBack() throws Exception { // 一系列的逻辑 // 需要事务操作更新订单和用户金额 orderBizService.updateOrderStatusAndUserBalance(); } @Override @Transactional(rollbackFor = Exception.class) public void upd ...
Spring 动态代理时是如何解决循环依赖的?为什么要使用三级缓存?
前言在研究 『 Spring 是如何解决循环依赖的 』 的时候,了解到 Spring 是借助三级缓存来解决循环依赖的。
同样在上一节留下了疑问:
循环依赖为什么要使用三级缓存?而不是使用二级缓存?
AOP 动态代理对循环依赖的有没有什么影响?
本篇文章也是围绕上面的内容进行展开。
笔记也在不断整理,之前可能会有点杂乱。
循序渐进,看一看什么是循环依赖?开始先简单回顾一下 Bean 的创建过程,当然小伙伴也可以直接阅读『 单例 Bean 的创建 』这篇文章。
不过考虑到阅读本文前再阅读上一篇文章、Debug 等等,会比较耗时,所以本篇文章前面一小部分会先对之前的文章内容做简要概括,也相当于对我自己学习的知识进行一个总结。
先来回顾一下三级缓存的概念。
singletonObjects: 一级缓存,存储单例对象,Bean 已经实例化,初始化完成。
earlySingletonObjects: 二级缓存,存储 singletonObject,这个 Bean 实例化了,还没有初始化。
singletonFactories: 三级缓存,存储 singletonFactory。
Bea ...
Spring 是如何解决循环依赖的?
前言相信很多小伙伴在工作中都会遇到循环依赖,不过大多数它是这样显示的:
还会提示这么一句:
Requested bean is currently in creation: Is there an unresolvable circular reference?
老铁!这就是发生循环依赖了!
当然这里是一个异常情况。
在我的一篇文章中介绍如何避免 Spring 自调用事务失效,其中网友给建议,说可以在类中注入自身,然后调用,而注入自身的过程也是循环依赖的处理过程。
下面就一起看一看,什么是循环依赖,以及 Spring 是如何解决循环依赖的?
什么是循环依赖
Dependency Resolution Process
Spring IoC 容器会在运行时检测到构造函数注入循环引用,并抛出 BeanCurrentlyInCreationException。
所以要避免构造函数注入,可以使用 setter 注入替代。
根据官方文档说明,Spring 会自动解决基于 setter 注入的循环依赖。
当然在咱们工作中现在都使用 @Autowired 注解来注入属性。
PS: @Autow ...
Spring 源码学习 16:单例 Bean 创建
前言在 finishBeanFactoryInitialization 中介绍了创建 Bean 的流程大概流程,这里进入单例 Bean 的创建过程。
这里主要分为三个部分创建单例 Bean
getSingleton
createBean
getObjectForBeanInstance
下面进入源码:
getSingletonpublic Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 加锁 synchronized (this.singletonObjects) { // 检查 singletonObjects 缓存中是否有 Object singletonObject = this.singletonObjects.get(beanName); if ...
Spring 源码学习 15:finishBeanFactoryInitialization(重点)
前言可以说前面的都是准备工作,而接下来开始的才是重点,在这一步会完成 BeanFactory 的初始化,同时实例化单例 Bean。
具体怎么操作的,那就一起阅读源码吧!
不过在阅读源码之前,还是需要了解一些知识的。
什么是 FactoryBean ?
FactoryBean 是如何使用的 ?
Bean 是如何初始化的?
常说的循环依赖是怎么解决的?
什么是 FactoryBean ?在官网的这篇文章《What’s a FactoryBean?》中有相关解答,有兴趣的小伙伴可以看一下。
由内部使用的对象实现的接口,这些对象 BeanFactory 本身就是单个对象的工厂。如果 bean 实现此接口,则它将用作对象公开的工厂,而不是直接用作将自身公开的 bean 实例。
注意:实现此接口的 bean 不能用作普通 bean。 FactoryBean以 bean 样式定义,但是为 bean 引用(getObject())公开的对象始终是它创建的对象。
FactoryBeans 可以支持单例和原型,并且可以按需延迟创建对象,也可以在启动时急于创建对象。
当生命一个 FactoryBean ...
Spring 源码学习 14:initApplicationEventMulticaster 、onRefresh 和 registerListeners
前言上一篇介绍了国际化的使用以及初始化消息源的源码,接下来接着往下阅读,将进入 initApplicationEventMulticaster 、onRefresh 和 registerListeners 的相关操作逻辑。
这一部分主要是初始化事件广播器以及注册监听器。而 onRefresh 部分则需要子类去实现。 所以本文主要介绍以下几个部分:
什么是 Spring 事件?
监听器是如何使用的?
什么是 Spring 事件?
这块的介绍在官网 1.15.2. Standard and Custom Events 部分有介绍。
Spring 通过 ApplicationEvent 类和 ApplicationListener 接口提供 ApplicationContext 中的事件处理。如果将实现 ApplicationListener 接口的 bean 部署到上下文中,则每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。本质上,这是标准的观察者设计模式。
归纳下来主要就是三个部分: 事件、事件发布者、事件监听器。 ...
Spring 源码学习 13:initMessageSource
前言在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。
依然如之前所示,先通过官网了解到国际化的用法,然后再对源码进行研究。
MessageSource 国际化
如官网1.15.1. Internationalization using MessageSource所示,主要作用就是使用国际化,定制不同的消息。
需要注意的是 MessageSource 定义的 Bean 名字必须为 messageSource, 而如果找不到则会默认注册 DelegatingMessageSource 作为 messageSource 的 Bean。
使用1. 创建国际化文件
2. 声明 MessageSource在 JavaConfig 中 声明 MessageSource , 记得名字一定要叫做 messageSource !
@Configuration@ComponentScan("com.liuzhihang")public class JavaConfig ...
Spring 源码学习 12:registerBeanPostProcessors
前言前面通过 invokeBeanFactoryPostProcessors 这一步了解到了什么是 BeanFactoryPostProcessor ,以及 BeanFactoryPostProcessor 的使用及作用,并通过 invokeBeanFactoryPostProcessors 这一步源码,对 BeanFactoryPostProcessor 的加载流程有了进一步了解。
现在就一起进入下一个环节:
registerBeanPostProcessors(beanFactory);
这一步主要的作用是加载 BeanPostProcessor,从名字也可以看出,只是加载,并没有执行。
不过,在进入源码之前,依然是结合官网,先了解以下几个问题:
什么是 BeanPostProcessor?
BeanPostProcessor 是如何使用的?
BeanPostProcessor 有什么用?
什么是 BeanPostProcessor ?
如截图所示,在官网 1.8.1 Customizing Beans by Using a BeanPostProcessor 中介绍, Bea ...
Spring 源码学习 11:invokeBeanFactoryPostProcessors
前言invokeBeanFactoryPostProcessors 会执行 BeanFactory 的后置处理器。看到这里会有疑问:
什么是 BeanFactoryPostProcessor ?
BeanfactoryPostProcessor 该如何使用?
知道了上面两个问题的答案,对 BeanFactoryPostProcessor 有了了解之后,然后再深入源码,继续阅读 invokeBeanFactoryPostProcessors 这个方法。
作用资料还是在官网可以找到答案:
阅读了一下,大概意思是 Spring IoC 容器允许 BeanFactoryPostProcessor 读取配置元数据,并有可能在容器实例化除 BeanFactoryPostProcessor 实例以外的任何 bean 之前更改它。
同样可以使用 Ordered 接口对 BeanFactoryPostProcessor 进行排序。
注意
BeanFactoryPostProcessor 操作的是 BeanDefinition ,即元数据。但是同样可以通过获取到 BeanFactory 进行实例化 ...
Spring 源码学习 10:prepareBeanFactory 和 postProcessBeanFactory
前言根据 refresh 流程,当 obtainFreshBeanFactory 执行结束后,下一步会执行 prepareBeanFactory ,顾名思义,这个方法主要是准备 BeanFactory,下面一起看一看这部分逻辑。
prepareBeanFactoryprotected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. // 设置beanFactory的类加载器 beanFactory.setBeanClassLoader(getClassLoader()); // spring.spel.ignore 属性控制是否解析 SpEL 表达式 if (!shouldIgnoreSpel) { beanFactory.setBeanExpressionResolver(new StandardBeanExpres ...