1、解析配置文件

1.1 、解析配置文件的阶段

处理配置文件是在 refresh => invokeBeanFactoryPostProcessors ,即在调用 BeanFactory后置处理器阶段 对配置文件进行解析。
其中有个ConfigurationClassPostProcessor 类,该类是BeanDefinitionRegistryPostProcessor接口类型,该接口定义了注册BeanDefinition的规范。
postProcessBeanDefinitionRegistry方法中创建ConfigurationClassParser对象,调用其parse方法来解析配置文件并注册相关的BeanDefinition。

⭐️ 关键点⭐️
refresh => invokeBeanFactoryPostProcessors
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
ConfigurationClassPostProcessor #postProcessBeanDefinitionRegistry
ConfigurationClassParser#.parse

1.2、解析配置文件的方式

具体的解析在解析过程是循环递归的,即会解析配置文件的注解,解析注解的注解…, 层层递归。

1.3、案例解析

首先看看递归解析注解的调用栈:

collectImports:525, ConfigurationClassParser (org.springframework.context.annotation) [2]
collectImports:520, ConfigurationClassParser (org.springframework.context.annotation) [1]
getImports:496, ConfigurationClassParser (org.springframework.context.annotation)
----------------------------------------------------------------------------------------------------
doProcessConfigurationClass:287, ConfigurationClassParser (org.springframework.context.annotation)
processConfigurationClass:226, ConfigurationClassParser (org.springframework.context.annotation)
parse:181, ConfigurationClassParser (org.springframework.context.annotation)
parse:149, ConfigurationClassParser (org.springframework.context.annotation)
processConfigBeanDefinitions:304, ConfigurationClassPostProcessor (org.springframework.context.annotation)
postProcessBeanDefinitionRegistry:220, ConfigurationClassPostProcessor (org.springframework.context.annotation)
invokeBeanDefinitionRegistryPostProcessors:290, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:89, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:703, AbstractApplicationContext (org.springframework.context.support)
refresh:520, AbstractApplicationContext (org.springframework.context.support)
main:17, TXSpringTest (com.yh.stu.spring.annotation.tx)

(1)找到配置类TXConf(processConfigBeanDefinitions:304)
(2)解析配置类(parse:149),
(3)循环递归找到@EnableTransactionManagement注解的注解@Import(TransactionManagementConfigurationSelector.class)
(4)


while TXConf 的配置{//1-processConfigurationClass//2-doProcessConfigurationClass@Component@ropertySource@ComponentScan{//1-processConfigurationClasswhile OrderDao 的配置{@Component@ropertySource@ComponentScan{空}for 递归 @Import 注解{}}}@Import{for递归收集注解中@Import导入的类,放入set中{......}例: (TXConf.java)事务配置TXConf的注解@EnableTransactionManagement的注解@Import(TransactionManagementConfigurationSelector.class)processImports方法for循环处理set中的3种类{1、ImportSelector类型的类 事务示例:TransactionManagementConfigurationSelector,实例化该类,然后调用它的接口方法selectImports,返回2个类名称的数组:return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};递归调用processImports方法,处理AutoProxyRegistrar、ProxyTransactionManagementConfiguration2、ImportBeanDefinitionRegistrar类型的类事务示例:AutoProxyRegistrar是这个类型的类,创建类对象,将其放入配置类TXConf包装类ConfigurationClass的Map属性中3、非以上两种类型事务示例:ProxyTransactionManagementConfiguration就是该类型,此时把该类当做类似TXConf的普通的配置类,以上所有的处理流程都要针对其进行处理。所以说整个配置文件的解析过程是个 “递归解析的过程” }}@ImportResource@Bean
}

⭐️总结一下
1、Spring中类似TXConf的配置文件是可以有多个的,while解析多个配置文件
2、处理@Import注解导入的类过程存在递归调用,分别是1、3两种类型,1递归processImports方法 、3递归processConfigurationClass方法

2、解析 ProxyTransactionManagementConfiguration ,得到4个类

上一节分析了配置文件的解析过程,我们这里把 ProxyTransactionManagementConfiguration 配置文件的解析过程独立出来分析,因为本类主要是和事务相关的内容。

我们看ProxyTransactionManagementConfiguration 的源码,都是通过@Bean标注的方法进行Bean的注册

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());if (this.enableTx != null) {advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}
}
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public static TransactionalEventListenerFactory transactionalEventListenerFactory() {return new TransactionalEventListenerFactory();}
}

⭐️ 解析出了4个类
1、BeanFactoryTransactionAttributeSourceAdvisor
2、AnnotationTransactionAttributeSource
3、TransactionInterceptor
4、TransactionalEventListenerFactory (父类)

3、注册BeanDefinition

解析完配置后,一切准备就绪,每个配置文件都会被封装为ConfigurationClass,此时new 一个ConfigurationClassBeanDefinitionReader对象,调用 loadBeanDefinitions(configClasses)。

一般情况下ConfigurationClass对象有多个,包括用户@Configuration配置的,还有配置文件中@ComponentScan扫描的,@Import注解中 “导入”的带@Configuration注解的。

loadBeanDefinitions for循环遍历多个ConfigurationClass
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {if (trackedConditionEvaluator.shouldSkip(configClass)) {String beanName = configClass.getBeanName();if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {this.registry.removeBeanDefinition(beanName);}this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());return;}if (configClass.isImported()) {registerBeanDefinitionForImportedConfigurationClass(configClass);SS.l("注册"+SS.sn(configClass.getBeanName())+" 配置类本身的 BeanDefinition.");}for (BeanMethod beanMethod : configClass.getBeanMethods()) {loadBeanDefinitionsForBeanMethod(beanMethod);}loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());}

上文提到了
【事务示例:
AutoProxyRegistrar是ImportBeanDefinitionRegistrar类型的类,创建类的对象,将其放入配置类TXConf包装类ConfigurationClass的Map属性中】
在最后一步,loadBeanDefinitionsFromRegistrars方法中会处理,AutoProxyRegistrar 的registerBeanDefinitions 方法中会注册InfrastructureAdvisorAutoProxyCreator,该类BeanPostProcessor接口的实现类。

3、创建Bean - BeanFactoryTransactionAttributeSourceAdvisor
创建TXConf实例时(doCreateBean(..)),initializeBean(..)方法对其进行初始化, for 循环遍历所有的BeanPostProcessor{调用InfrastructureAdvisorAutoProxyCreator.postProcessAfterInitialization(..){wrapIfNecessary(..){// 对TXConf实例尝试创建代理对象从BeanFactory中找出所有的Advisor,发现BeanFactoryTransactionAttributeSourceAdvisor的 Bean 还没有创建该创建 BeanFactoryTransactionAttributeSourceAdvisor 的Bean{调用 ProxyTransactionManagementConfiguration#transactionAdvisor创建BeanFactoryTransaction???Advisor// 注意:BeanFactoryTransactionAttributeSourceAdvisor 是通过 @Bean 方法创建的,transactionAdvisor方法中还调用了// 其他两个方法              }}}
}

方法 ProxyTransactionManagementConfiguration#transactionAdvisor 如下:

 @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());if (this.enableTx != null) {advisor.setOrder(this.enableTx.<Integer>getNumber("order"));}return advisor;}

4、用 InfrastructureAdvisorAutoProxyCreator 创建代理对象

在创建OrderSerivceImpl对象后,对象进行初始化(AbstractAutowireCapableBeanFactory#initializeBean)。
调用 InfrastructureAdvisorAutoProxyCreator(BeanPostProcessor类型 )的 applyBeanPostProcessorsAfterInitialization 方法,方法中调用对需要代理的对象进行创建代理对象(AbstractAutoProxyCreator#wrapIfNecessary)

wrapIfNecessary:342, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:293, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:385, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1740, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:551, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:471, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:277, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 854507466 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$12)
getSingleton:211, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:275, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:155, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:802, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:876, AbstractApplicationContext (org.springframework.context.support)
refresh:544, AbstractApplicationContext (org.springframework.context.support)
main:17, TXSpringTest (com.yh.stu.spring.annotation.tx)
4.1、获取Bean的Advisor

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

findCandidateAdvisors()方法会找出所有的 Advisor 对象,包括 BeanFactoryTransactionAttributeSourceAdvisor 类的对象
findAdvisorsThatCanApply方法找出Bean适用的Advisor对象,比如 BeanFactoryTransactionAttributeSourceAdvisor 类的对象

4.2、createProxy 创建代理对象

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);}ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}//确定给定bean的advisor,包括特定的拦截器和通用的拦截器,所有这些都是Advisor接口的实现类。Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}return proxyFactory.getProxy(getProxyClassLoader());}

ProxyFactory#getProxy方法返回 DefaultAopProxyFactory 类型的对象

    public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}

DefaultAopProxyFactory#createAopProxy 方法 返回 JdkDynamicAopProxy 或 ObjenesisCglibAopProxy,参考

    @Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}

5、调用加了@Transaction 注解的方法

TransactionAspectSupport#invokeWithinTransaction

invokeWithinTransaction:286, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:98, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:209, JdkDynamicAopProxy (org.springframework.aop.framework)
queryAll:-1, $Proxy22 (com.sun.proxy)
main:18, TXSpringTest (com.yh.stu.spring.annotation.tx)

说说事务未生效的几种情况?

为什么我的事务不生效
1.如果不是Innodb存储引擎,MyISAM不支持事务。
2.没有指定rollbackFor参数。
3. 没有指定transactionManager参数,默认的transactionManager并不是我期望的,以及一个事务中涉及到了多个数据库。
4. 如果AOP使用了JDK动态代理,对象内部方法互相调用不会被Spring的AOP拦截,@Transactional注解无效。
5. 如果AOP使用了CGLIB代理,事务方法或者类不是public,无法被外部包访问到,或者是final无法继承,@transactional注解无效。

https://www.cnblogs.com/dennyzhangdd/p/9602673.html

Spring源码 (事务篇) - 整体流程相关推荐

  1. 【06】Spring源码-分析篇-ApplicationContext

    Spring源码篇-ApplicationContext   前面通过手写IoC,DI.AOP和Bean的配置.到最后ApplicationContext的门面处理,对于Spring相关的核心概念应该 ...

  2. Spring源码——动态AOP实现流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  3. Spring源码分析篇(一)之Gradle环境搭建

    Gradle的简介我就不在此多废话了,我们直接上步骤 本人的操作环境是mac jdk1.8+spring5.x版本 编译工具:IDEA IntelliJ 一.熟悉你需要的spring源码包 这个源码包 ...

  4. SpringIOC源码——管理型容器——整体流程【框架专题】

    SpringIOC源码--外部流程与结构 public void refresh() throws BeansException, IllegalStateException {         sy ...

  5. MMKV_微信MMKV源码分析(一) | 整体流程

    在使用MMKV框架前,需调用以下方法进行初始化 MMKV.initialize(context); 复制代码 这里的 Java 层主要是获取到保存文件的路径,传入Native层,这里默认的路径是APP ...

  6. 从Spring源码探究IOC初始化流程

    随着不断地使用Spring,以及后续的Boot.cloud,不断的体会到这个拯救Java的生态体系的强大,也使我对于这个框架有了极大的好奇心,以至于产生了我为什么不能写一个这样的框架的思考. 通过自学 ...

  7. Spring源码——声明式事务流程

    前言 最近回顾了一下Spring源码,准备用思维导图的方式简单的将整个源码内容的流程展示出来,思维导图.图片等文件更新在https://github.com/MrSorrow/spring-frame ...

  8. 从Spring源码探究DI属性注入流程

    随着不断地使用Spring,以及后续的Boot.cloud,不断的体会到这个拯救Java的生态体系的强大,也使我对于这个框架有了极大的好奇心,以至于产生了我为什么不能写一个这样的框架的思考. 通过自学 ...

  9. 从Spring源码探究AOP代码织入的过程

    随着不断地使用Spring,以及后续的Boot.cloud,不断的体会到这个拯救Java的生态体系的强大,也使我对于这个框架有了极大的好奇心,以至于产生了我为什么不能写一个这样的框架的思考. 通过自学 ...

最新文章

  1. .java编写一个梯形类lader_能够完成相关计算above为高_【Java】编写一个应用程序计算梯形和圆形的面积...
  2. 组合逻辑和时序逻辑学习笔记
  3. Sequential 顺序模型和 Model 模型【TensorFlow2入门手册】
  4. ifix从sqlserver里读数据_ifix连接SQL和读写EXCEL的方法
  5. SpringBoot 中常用注解@PathVaribale/@RequestParam/@GetMapping介绍
  6. ansys怎么使用anand模型_【干货】经典ANSYS 与 Workbench如何实现联合仿真,相互切换操作。...
  7. Windows Server 2008 多元密码策略配置
  8. csdn发布文章无法查看
  9. mysql 集群操作系统_mysql集群部署
  10. PIC浅谈--《x86/x64体系探索及编程》试读
  11. 你认识什么是前端吗?你是合格的前端吗?
  12. Ubuntu/Linux备份/还原系统
  13. fiddler4安装及使用手机抓包
  14. 北斗输电杆塔状态在线监测系统
  15. 点序AS2258量产详尽图文教程以及量产工具固件下载,保姆级教程
  16. SSRS报表服务随笔(rdl报表服务)-报表结构与样式
  17. 微软中国CEO梁念坚 : Windows Phone有四大优点
  18. 微信小程序image背景图片全屏显示(根据设备高度自适应背景图片)
  19. c语言教学方法措施,C语言教学方法探讨
  20. 一个计算机游戏机,我想入手一台游戏主机,ps、xbox、任天堂相比,哪个好?

热门文章

  1. [译] Dojo 工具包参考手册
  2. java mail header_java使用mail发送邮件时出现乱码如何解决
  3. Python中使用xpath结合contains
  4. python getsize_Python getsizeof()和getsize()区分详解
  5. HibernateUtil类(可用于连接多个数据库)
  6. vue ---- 数组的常用方法
  7. SQL--查询无记录,显示默认一条记录
  8. linux运维中的中间件,linux中间件Nginx的安装过程
  9. python数据字典排序_Python自动处理数据字典(Python是3.6版本)
  10. int与bigdecimal的相互转换