spring知识点
2023-09-17 17:43:55 15 举报
AI智能生成
spring循环依赖,事务,整合mybaties的实现原理
作者其他创作
大纲/内容
spring事务
事务执行原理
开启事务配置
@EnableTransactionManagement
@Import({TransactionManagementConfigurationSelector.class})
添加AutoProxyRegistrar的bean
注册InfrastructureAdvisorAutoProxyCreator
继承AbstractAdvisorAutoProxyCreator
继承AbstractAdvisorAutoProxyCreator
添加ProxyTransactionManagementConfiguration的bean
BeanFactoryTransactionAttributeSourceAdvisor
AnnotationTransactionAttributeSource
TransactionInterceptor
执行事务方法,@Transaction注解的方法开始执行
TransactionInterceptor.invoke()
invokeWithinTransaction
获取AnnotationTransactionAttributeSource,可以用来解析Transaction注解
TransactionAttributeSource tas = this.getTransactionAttributeSource();
获取@Transaction注解的属性信息,比如事务的隔离级别、传播机制等
TransactionAttribute
TransactionAttribute
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
获取事务管理器:TransactionManager
TransactionManager tm = this.determineTransactionManager(txAttr);
转换事务管理器:PlatformTransactionManager
PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);
开启事务:createTransactionIfNecessary
PlatformTransactionManager.getTransaction
AbstractPlatformTransactionManager.getTransaction
已经存在,返回存在的事务
@Transaction上面的timeout属性小于-1,直接抛异常
判断传播属性PROPAGATION_MANDATORY,是的话抛异常
开启事务:startTransaction
DataSourceTransactionManager.doBegin
获取数据库连接
修改commit的属性
设置readonly
设置隔离级别
读未提交
读已提交
可重复度(默认隔离级别)
序列化
设置超时时间
执行业务代码
成功,提交事务
判断是不是要强制回滚
判断是否已经提交
失败,回滚事务
根据@Transaction注解的rollbackFor配置的异常回滚
执行finally逻辑
恢复被挂起的资源
事务传播机制
事务的分类
融入:B事务方法调用A事务方法,如果A存在事务使用A事务
挂起:将A事务挂起,spring通过ThreadLocal来实现
嵌套:通过设置保存点来实现
事务的传播行为
PROPAGATION_REQUIRED:表示如果当前存在事务,融入当前事务,如果没有事务新建事务
PROPAGATION_SUPPORTS:表示当前如果存在事务,融入当前事务,没有则以非事务方式运行(不开启事务)
PROPAGATION_MANDATORY:表示当前如果存在事务,融入当前事务,如果没有事务则会抛出异常
PROPAGATIONREQUIRES_NEW:表示如果当前存在事务,则挂起当前事务,执行现在的事务;如果外面没有事务,开启自身独立的事务
PROPAGATION_TNOT_SUPPORTS:表示如果当前存在事务,则挂起当前事务,以非事务方式运行;如果外面没有事务,直接以非事务方式运行
PROPAGATION_NEVER:表示当前必须没有事务,如果有事务则会抛出异常
PROPAGATION_NESTED:表示如果存在事务,嵌套进当前事务当中,支持回滚操作;如果不存在则使用Requeired的传播行为
事务的隔离级别
读未提交
读已提交
可重复度(默认)
序列化
事务失效的几种情形
循环依赖
产生原因
在bean的生命周期过程当中,在进行属性填充的时候,如果A依赖B,而且B也依赖A,去单例池获取依赖的对象的时候获取不到所依赖的对象则会创建新的对象
那么这种情况会循环创建
那么这种情况会循环创建
解决思路
就是循环依赖产生的时候有一个中间的缓存,存入未完全初始化完的对象,那么初始化B的时候发现依赖A,创建A的时候去这个缓存当中找一下有没有A,如果有A则终止循环依赖
基于上面思路产生的问题
二级缓存只是存入的未完全初始化的对象,如果这个对象需要AOP代理,而AOP代理则是在生命周期的初始化后,那么产生的这个对象则会不一致
产生上面的情形可以有一个解决思路,就是在B创建的时候,先创建A,A如果有代理,则先创建代理再放入二级缓存,但是这样的话没有经过后面的完整生
生命周期
产生上面的情形可以有一个解决思路,就是在B创建的时候,先创建A,A如果有代理,则先创建代理再放入二级缓存,但是这样的话没有经过后面的完整生
生命周期
如何判断出现了循环依赖?
A依赖B,B也依赖A;当创建A的时候先记录正在创建中的Bean为A,当创建A当中的B的时候再去创建A的时候比较一下当前的创建Bean是不是A,是就出现了循环依赖
spring容器中重要的三级缓存
一级缓存:singletonObjects
保存经过完整生命周期的bean
保存经过完整生命周期的bean
二级缓存:缓存未经过完整生命周期的bean,如果某个bean出现了循环依赖,就会提前把这个暂时未经过完整生命周期的bean放入earlySingletonObjects中,这个bean如果要经过AOP,那么就会把代理对象放入earlySingletonObjects中,否则就是把原始对象放入earlySingletonObjects,但是不管怎么样,就是是代理对象,代理对象所代理的原始对象也是没有经过完整生命周期的,所以放入earlySingletonObjects我们就可以统一认为是未经过完整生命周期的bean。
还有一种情况就是:如果A依赖B和C,在创建B的时候如果A已经放入earlySingletonObjects里面了,这个时候创建的时候是不需要再创建A的不需要再一次经过AOP,应为创建B已经AOP了,保证单例
还有一种情况就是:如果A依赖B和C,在创建B的时候如果A已经放入earlySingletonObjects里面了,这个时候创建的时候是不需要再创建A的不需要再一次经过AOP,应为创建B已经AOP了,保证单例
三级缓存:缓存的是一个ObjectFactory,也就是一个Lambda表达式。在每个Bean的生成过程中,经过实例化得到一个原始对象后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式可能用到,也可能用不到,如果当前Bean没有出现循环依赖,那么这个Lambda表达式没用,当前bean按照自己的生命周期正常执行,执行完后直接把当前bean放入singletonObjects中,如果当前bean在依赖注入时发现出现了循环依赖(当前正在创建的bean被其他bean依赖了),则从三级缓存中拿到Lambda表达式,并执行Lambda表达式得到一个对象,并把得到的对象放入二级缓存((如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象))
思考:怎样去spring容器当中拿一个bean?
先去一级缓存拿,再去二级缓存,最会再去三级缓存拿
先去一级缓存拿,再去二级缓存,最会再去三级缓存拿
回顾bean的产生过程
spring扫描得到BeanDefinetion
根据BeanDefinetion生成Bean对象
根据推断出来的构造方法得到一个原始对象
填充属性,也叫作依赖注入
填充属性基本逻辑:先去单例池里面找有没有,如果没有则会创建
如果某个方法被AOP会生成代理对象
将代理对象放入单例池
bean的生命周期当中实例化的时候会调用doCreatBean方法
执行 applyMergedBeanDefinitionPostProcessors
postProcessMergedBeanDefinition
AutowiredAnnotationBeanPostPreoccer.postProcessMergedBeanDefinition
寻找@Autowired的属性
寻找@Autowired的方法
属性填充populateBean
AutowiredAnnotationBeanPostProcessor..postProcessProperties()
初始化 initializeBean
注册销毁的逻辑
属性填充
AutowiredAnnotationBeanPostProcessor..postProcessProperties()
findAutowiringMetadata
buildAutowiringMetadata
填充属性上带有@Autowired的注解的属性
AutowiredFieldElement.inject
填充方法上带有@Autowired的注解的方法
AutowiredMethodElement.inject
CommonAnnotationBeanPostProcessor.postProcessProperties()
SourceElement.inject
解决循环依赖
创建bean的时候也就是doCreatBean的时候会进行判断,如果是单例并且正在创建先将B的ObjectFactory加入三级缓存
属性赋值获取bean的时候会去三级缓存拿,能够拿到那的是一个lamd表达式,里面会执行getObjecy然后执行wrapIfNecess,里面会进行判断如果有AOP则产生的是代理对象,如果没有AOP则产生原始对象
AOP动态代理的时候会通过AbstractAutoProxyCreator产生动态代理,会wrapIfNecess,也是判断是否有AOP,有就动态代理,没有则返回原始对象
springMVC
spring的整合
整合myBaties:整合原理,将Dao层的接口注入到spring当中交给spring管理,
并且通过@Autowired注解能够注入代理对象
并且通过@Autowired注解能够注入代理对象
前置知识点
FactoryBean的调用时机
getBean
doCreatBean
判断单例、原型、是不是有父类FactoryBean等
getObjectForBeanInstance
super.getObjectForBeanInstance
getObjectFromFactoryBean
doGetObjectFromFactoryBean
FactoryBean.getObject();
整合过程
扫描获取所有的接口类,并且将所有扫描出来的bean转换成FactoryBean
新增myBaties扫描注解@MapperScan,申明扫描路径
@MapperScan增加ImportBeanDefinetionRegisterPostProcessor
MapperScanRegister
实现了ImportBeanDefinetionRegisterPostProcessor
执行ImportBeanDefinetionRegisterPostProcessor.registerBeanDefinitions
获取扫描路径:AnnotationMetadata。getAllAnnotationAttributes。get("path")
开启扫描逻辑 //自定义扫描起继承自ClassPathMapperScanner,
重写doScan和增加addExcludeFilter为匹配所有的类为true
重写doScan和增加addExcludeFilter为匹配所有的类为true
扫描到所有beanDefinetion以后修改beaName为FactoryBean和添加对应的构造方法赋值
容器遍历所有的BeanDefinetion进行属性赋值的时候会进行判断,
如果是Factorybean则最终会调用FactoryBean.getObject方法生成jdk动态代理对象
如果是Factorybean则最终会调用FactoryBean.getObject方法生成jdk动态代理对象
FactoryBean.getObject
SqlSession.getMapper
jdk动态代理
Proxy.newProxyInstance(ClassLoader,XXX.class,InvocationHandler)
执行动态代理的方法
getMapgger
SessionFactory.Opensession
session.selectOne
配置文件解析
sql执行
0 条评论
下一页