spring 事务管理实现方式
来源:互联网 发布:音乐壁纸动态软件 编辑:程序博客网 时间:2024/05/18 00:30
注意:这里只是分析spring事务的实现方式。也就是spring的事务管理是怎么发生作用的,而不分析具体的实现细节
Spring是通过NameSpaceHandler来解析配置文件中的标签的。下面就已事务的配置为例,讲述一下
事务配置的标签的解析过程,从来理解事物是如何通过aop产生作用的。
以上的配置相信很多人已经很熟悉了,在此不赘述。而是具体分析一下原理。
先来分析<tx:advice>...</tx:advice>。
tx是TransactionNameSpace可从/spring-tx/src/main/resources/META-INF/spring.handlers中得到对应的是handler是TxNamespaceHandler.
http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler
这个类一个init方法:
public void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}
这个方法是在DefaultNamespaceHandlerResolver的resolve中调用的。在为对应的标签寻找namespacehandler的时候,调用这个resolve方法。resolve方法先寻找namespaceUri对应的namespacehandler,如果找到了就先调用Init方法。
OK.我们的<tx:advice>对应的解析器也注册了,那就是上面代码里面的
<pre name="code" class="java">new TxAdviceBeanDefinitionParser()
那么,这个解析器是什么时候调用的哪?
上一篇提到了,对应标签解析时会先选择namespacehandler,然后调用其parse方法。
TxNamespaceHandler的parse方法在其父类NamespaceHandlerSupport中,代码如下:
public BeanDefinition parse(Element element, ParserContext parserContext) {return findParserForElement(element, parserContext).parse(element, parserContext);}
这下明白了吧?<tx:advice>在解析出来的Document里面是一个Element,而这个Element的parse就是上面注册了的
TxAdviceBeanDefinitionParser
现在这个parser的parse方法在NamespaceHandlerSupport的parse方法中被调用了,下面我们来看看这个
TxAdviceBeanDefinitionParser的parse方法吧,这个方法在TxAdviceBeanDefinitionParser的祖父类AbstractBeanDefinitionParser中:
public final BeanDefinition parse(Element element, ParserContext parserContext) {AbstractBeanDefinition definition = parseInternal(element, parserContext);if (definition != null && !parserContext.isNested()) {try {String id = resolveId(element, definition, parserContext);if (!StringUtils.hasText(id)) {parserContext.getReaderContext().error("Id is required for element '" + parserContext.getDelegate().getLocalName(element)+ "' when used as a top-level tag", element);}String[] aliases = new String[0];String name = element.getAttribute(NAME_ATTRIBUTE);if (StringUtils.hasLength(name)) {aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));}BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);registerBeanDefinition(holder, parserContext.getRegistry());if (shouldFireEvents()) {BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);postProcessComponentDefinition(componentDefinition);parserContext.registerComponent(componentDefinition);}}catch (BeanDefinitionStoreException ex) {parserContext.getReaderContext().error(ex.getMessage(), element);return null;}}return definition;}
注意其中这样一行:
<pre name="code" class="java">AbstractBeanDefinition definition = parseInternal(element, parserContext);
这个parseInternal是在TxAdviceBeanDefinitionParser的父类AbstractSingleBeanDefinitionParser中实现的,代码如下:
protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();String parentName = getParentName(element);if (parentName != null) {builder.getRawBeanDefinition().setParentName(parentName);}Class beanClass = getBeanClass(element);if (beanClass != null) {builder.getRawBeanDefinition().setBeanClass(beanClass);}else {String beanClassName = getBeanClassName(element);if (beanClassName != null) {builder.getRawBeanDefinition().setBeanClassName(beanClassName);}}builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));if (parserContext.isNested()) {// Inner bean definition must receive same scope as containing bean.builder.setScope(parserContext.getContainingBeanDefinition().getScope());}if (parserContext.isDefaultLazyInit()) {// Default-lazy-init applies to custom bean definitions as well.builder.setLazyInit(true);}doParse(element, parserContext, builder);return builder.getBeanDefinition();}
其中有一行:
Class beanClass = getBeanClass(element);
getBeanClass是在TxAdviceBeanDefinitionParser中实现的,很简单:
<pre name="code" class="java">protected Class getBeanClass(Element element) {return TransactionInterceptor.class;}
至此,这个标签解析的流程已经基本清晰了。那就是:解析除了一个以TransactionInerceptor为classname的beandefinition并且注册这个bean。剩下来要看的,就是这个TranscationInterceptor到底是什么?
看看这个类的接口定义,就明白了:
<pre name="code" class="java">public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable
这根本就是一个spring AOP的advice嘛!现在明白为什么事务的配置能通过aop产生作用了吧?
下面具体看看这个advice的advice:
<pre name="code" class="java">public Object invoke(final MethodInvocation invocation) throws Throwable {// Work out the target class: may be <code>null</code>.// The TransactionAttributeSource should be passed the target class// as well as the method, which may be from an interface.Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);// If the transaction attribute is null, the method is non-transactional.final TransactionAttribute txAttr =getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);final PlatformTransactionManager tm = determineTransactionManager(txAttr);final String joinpointIdentification = methodIdentification(invocation.getMethod());if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {// Standard transaction demarcation with getTransaction and commit/rollback calls.TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal = null;try {// This is an around advice: Invoke the next interceptor in the chain.// This will normally result in a target object being invoked.retVal = invocation.proceed();}catch (Throwable ex) {// target invocation exceptioncompleteTransactionAfterThrowing(txInfo, ex);throw ex;}finally {cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);return retVal;}else {// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.try {Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,new TransactionCallback<Object>() {public Object doInTransaction(TransactionStatus status) {TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);try {return invocation.proceed();}catch (Throwable ex) {if (txAttr.rollbackOn(ex)) {// A RuntimeException: will lead to a rollback.if (ex instanceof RuntimeException) {throw (RuntimeException) ex;}else {throw new ThrowableHolderException(ex);}}else {// A normal return value: will lead to a commit.return new ThrowableHolder(ex);}}finally {cleanupTransactionInfo(txInfo);}}});// Check result: It might indicate a Throwable to rethrow.if (result instanceof ThrowableHolder) {throw ((ThrowableHolder) result).getThrowable();}else {return result;}}catch (ThrowableHolderException ex) {throw ex.getCause();}}}
哦,原来就是在这里控制了method invocation(spring aop是基于method的)!根据我们的配置,来决定
是不是对method使用事务。
至此,spring的事务管理已经基本清晰了。就是解析出一个advice bean(of class : TransactionInterceptor)来,
然后在aop中配置pointcut和这个advice,就能产生作用了!
原文: http://michael-softtech.iteye.com/blog/813835 稍作修改
- spring 事务管理实现方式
- Spring事务管理方式实现
- spring的事务管理有几种方式实现
- spring的事务管理有几种方式实现
- spring 声明式事务管理xml方式实现
- spring 声明式事务管理注解方式实现
- spring源码分析之——spring 事务管理实现方式
- spring的事务管理方式!
- spring事务管理方式
- Spring中的事务管理方式
- spring事务管理方式
- spring 事务管理的方式
- Spring中的事务管理方式
- spring事务管理方式
- spring事务管理方式
- spring的事务管理有几种方式实现,如何实现
- spring的事务管理有几种方式实现,如何实现
- spring的事务管理有几种方式实现,如何实现
- fstream的使用和打开时存在中文中文路径可能失败的问题,其他中文问题都可以尝试采用如下方法
- LNMP环境下php-fpm启动脚本
- AsyncTask的使用方法
- python在window中显示内存对象关系图objgraph出错的应对办法
- 【error】LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value
- spring 事务管理实现方式
- Gridview 设置行高
- 简单的日期比较
- IOS 将数据按某个关键词排序
- 优秀的用户界面设计
- socket 乱码解决
- [C#] Direct2D 学习笔记 (一)
- 定位
- SQL Server数据库优化实战(三)