14、Spring源码之事务核心对象的创建

背景:

很多小伙伴看Spring事务的的逻辑时 总是看到一些Bean已经存在了容器、这些Bean甚至有了一些属性,是如何初始化进去的,一头雾水、可能”知所以然、不知其然“,了解这些spring事务的相关Bean的创建过程我觉得很重要、这里记录一下。spring事务是aop的思想实现的、所以建议不懂spring aop的可以看一下 我上两章写的东西,手动跟踪一下源码,,肯定有不少的收获!


事务配置:

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<constructor-arg  ref="dataSource"/>
	</bean>
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="driverClassName" value="${jdbc.driver.class.name}"/>
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<constructor-arg ref="dataSource"/>
	</bean>
	<aop:config>
		<aop:pointcut id="txPointCut" expression="execution(* com.zhangfuyin.aop.tx.OrderService.*(..)))"/>
		<aop:advisor advice-ref="myAdvice" pointcut-ref="txPointCut"></aop:advisor>
	</aop:config>

	<tx:advice id="myAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="*"/>
			<tx:method name="get*" read-only="true"/>
		</tx:attributes>
	</tx:advice>

思考一下问题、不看源码,借鉴spring aop源码逻辑,如果我们需要实现事务 需要准备那些东西?

1、Pointcut:  应用需要知道 那些类 甚至哪些方法需要事务的支持?

2、Advisor:   开启事务(beforeAdvosor)、提交事务(AfterAdvosor)、回滚事务                    (AfterThrowingAdvior) 这些通知器需要加载进容器,不同时机进行通知调用?

3、MethodInterceptor:   在spring具体通知需要链得方式进行Advisor的调用 ?

4、AspectjAwareAdvisorAutoProxyCreator 这是创建Advisor到容器的和创建代理对象的核心类?

以上问题 只是我们看源码前自己的思考和猜测,不一定正确。带着自己的疑问,进入源码的跟踪学习。


配置文件加载:

1、首先需要把bean的获取Bean的定义信息、直接进入到对<aop-config>标签的解析

1、configureAutoProxyCreator(parserContext, element) 向容器中注册了AspectJAwareAdvisorAutoProxyCreator 这个最核心的类。

2、根据<aop:config>这个标签下有两个子标签、开始对子标签的解析工作

3、parsePointcut方法开始解析<aop:pointcut>这个标签 核心功能向容器中注册了AspectJExpressionPointcut的定义信息(RootBeanDefinition)

4、parseAdvisor方法开始解析<aop:advisor>这个标签、核心功能是向容器注册了DefaultBeanFactoryPointcutAdvisor的定义信息(RootBeanDefinition), 和给定义信息的propertyValueList添加两个值分别是:
  ①PropertyValue(adviceBeanName, RuntimeBeanNameReference(myAdvice))

  ②PropertyValue(pointcut, RuntimeBeanReference(txPointcut))

5、此时<aop:config> 解析结束 、开始解析<aop:advice>标签 核心功能是向容器注册了注册了TransactionInterceptor的Bean的定义信息(GenericBeanDefinition)其实向属性列表中添加了propertyValueList添加两个值分别是:

①PropertyValue(transactionManager, RuntimeBeanReference(transactionManager))

②PropertyValue(transactionAttributeSource, RootBeanDefinition(NameMatchTransactionAttributeSource))

其中说明一下NameMatchTransactionAttributeSource 主要封装了<tx:attributes>标签下的内容、其中Spring会对NameMatchTransactionAttributeSource 添加属性PropertyValue(nameMap, ManagedMap(TypedStringValue,  TypedStringValue,.........................))这样的结构

6、此时对配置文件的加载结束、看似结构很繁琐、实际就是对配置文件的包装而已。但是这里我们必须要清楚、这里只是进行了配置文件的读取 这些实际Bean的对象都没有实例化、而且这里注册进容器的BeanDefinition很多是有propertyValueList属性、这些属性在创建Bean对象的时候 肯定也要实例化的、也就是说创建的Bean如果propertyValueList不为空、那么会进入”套娃“ 进行相关属性值的实例化、代码会疯狂递归、debug到这里的时候不要晕。

7、 总结:Spring事务提前要准备哪些Bean?

     ①Pointcut:  AspectJExpressionPointcut

     ②Advisor:   DefaultBeanFactoryPointcutAdvisor

     ③MethodInterceptor:   TransactionInterceptor   ------> NameMatchTransactionAttributeSource

     ④核心类 AspectjAwareAdvisorAutoProxyCreator

有些猜测是对的 、有些有一些出入、先不管具体Spring是怎么来控制事务的、但此时我们知道了Spring为了支持事务、准备的一些Bean信息和如何包装这些Bean信息。

 Bean的创建

1、任意普通类生命周期开始。挨着排的从BeanDefinitonNames中获取BeanDefinition、第一个为OrderService、要清楚之前有一个AspectAwareAdvisorAutoProxyCreator这BPP已经注册进容器并创建完成。我们看一下Spring在创建第一个普通Bean(OrderService)的时候是如何把事务相关的Bean初始化完成的。

2、开始创建DefautBeanFactoryPointcutAdvosor。创建OrderService会进入到BPP的postProcessBeforeInstantiation方法、此时shouldSkip方法会从BeanDefinition中获取Advisor类型 、很明显从容器中获取到DefautBeanFactoryPointcutAdvosor,此时会进入DefautBeanFactoryPointcutAdvosor的生命周期逻辑

3、开始对DefaultBeanFactoryPointcutAdvisor的propertyValueList进行实例化。resolveVauleIfNecessary方法 又会对这两个参数的Bean生命周期过程。 这两个参数Bean的生命周期这里不再赘述。

4、DefaultBeanFactoryPointcutAdvisor反射机制给属性赋值。populateBean()把Bean转化为BeanWapper对象、设置BeanWapper的propertyValues属性、其实这里就是包装了一下 并设置好转后后的属性值。initializeBean()方法 根据属性列表、通过反射机制给属性赋值。

5、跳回到OrderService的创建过程。总结下,目前为止Spring已经完成了这些Aop相关的Bean的创建.

     ①Pointcut:  AspectJExpressionPointcut   
     ②Advisor:   DefaultBeanFactoryPointcutAdvisor
     ③AspectjAwareAdvisorAutoProxyCreator

6、开始创建OderSerivce的代理对象。执行BPP的postProcessAfterInitialization()方法调用wrapIfNecessary().

7、 获取容器内所有Advisor对象。根据Advisor的Pointcut属性来判断否可以适用到当前对象。

8、Advise的对象的创建。上一个截图extendAdvisor方法会调用makeAdvisorChainAspectJCapableIfNecessary方法、isAspectJAdvice方法里的getAdvice方法根据adviceBeanName又会进入TransactionInterceptor的生命周期逻辑、TransactionInterceptor又会进入NameMatchTransactionAttributeSource的生命周期。值得注意的是这个类属于MethodInterceptor, 同时属于Advice。


 

9、此时Spring事务相关的TransactionInterceptor 和 NameMatchTransactionAttributeSource也创建完毕。

10、此时DefaultBeanFactoryPointcutAdvisor的内存结构如图。

11、此时所有事务相关的核心Bean创建完毕、可以对OrderService生成代理类了。后面一章我们看下Spring事务的执行逻辑。

  • 25
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值