- 浏览: 546506 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
wa114d:
楼主工作几年了,好厉害
一个面试官对面试问题的分析 -
wobuxiaole:
Good,非常好
30岁前男人需要完成的事 -
小逗逗:
Good,非常好
30岁前男人需要完成的事 -
invincibleLiu:
好帖,要顶!(别投我隐藏啊,这是对BBS最原始一种支持)
Java:synchronized修饰符在静态方法与非静态方法上的区别 -
fayedShih:
第三题,不知道对不对
import java.util.con ...
企业牛逼面试题目 高手进来讨论答题
我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码中,使得事务管理代码和业务代码解藕。在这种方式我们结合IoC容器和Spirng已有的FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等。其中最简单的方式就是通过配置TransactionProxyFactoryBean来实现声明式事物;
在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物管理有这么几个部分:
* 对在上下文中配置的属性的处理,这里涉及的类是TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性信息放在TransactionAttribute中来使用,而这些属性的处理往往是和对切入点的处理是结合起来的。对属性的处理放在类TransactionAttributeSource中完成。
* 创建事物的过程,这个过程是委托给具体的事物管理器来创建的,但Spring通过TransactionStatus来传递相关的信息。
* 对事物的处理通过对相关信息的判断来委托给具体的事物管理器完成。
我们下面看看具体的实现,在TransactionFactoryBean中:
- public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
- implements FactoryBean, BeanFactoryAware {
- //这里是Spring事务处理而使用的AOP拦截器,中间封装了Spring对事务处理的代码来支持声明式事务处理的实现
- private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
- private Pointcut pointcut;
- //这里Spring把TransactionManager注入到TransactionInterceptor中去
- public void setTransactionManager(PlatformTransactionManager transactionManager) {
- this.transactionInterceptor.setTransactionManager(transactionManager);
- }
- //这里把在bean配置文件中读到的事务管理的属性信息注入到TransactionInterceptor中去
- public void setTransactionAttributes(Properties transactionAttributes) {
- this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
- }
- .........中间省略了其他一些方法.......
- //这里创建Spring AOP对事务处理的Advisor
- protected Object createMainInterceptor() {
- this.transactionInterceptor.afterPropertiesSet();
- if (this.pointcut != null) {
- //这里使用默认的通知器
- return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
- }
- else {
- // 使用上面定义好的TransactionInterceptor作为拦截器,同时使用TransactionAttributeSourceAdvisor
- return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
- }
- }
- }
<script></script>
那什么时候Spring的TransactionInterceptor被注入到Spring AOP中成为Advisor中的一部分呢?我们看到在TransactionProxyFactoryBean中,这个方法在IOC初始化bean的时候被执行:
- public void afterPropertiesSet() {
- .......
- //TransactionProxyFactoryBean实际上使用ProxyFactory完成AOP的基本功能。
- ProxyFactory proxyFactory = new ProxyFactory();
- if (this.preInterceptors != null) {
- for (int i = 0; i < this.preInterceptors.length; i++) {
- proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.preInterceptors[i]));
- }
- }
- //这里是Spring加入通知器的地方
- //有两种通知器可以被加入DefaultPointcutAdvisor或者TransactionAttributeSourceAdvisor
- //这里把Spring处理声明式事务处理的AOP代码都放到ProxyFactory中去,怎样加入advisor我们可以参考ProxyFactory的父类AdvisedSupport()
- //由它来维护一个advice的链表,通过这个链表的增删改来抽象我们对整个通知器配置的增删改操作。
- proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));
- if (this.postInterceptors != null) {
- for (int i = 0; i < this.postInterceptors.length; i++) {
- proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(this.postInterceptors[i]));
- }
- }
- proxyFactory.copyFrom(this);
- //这里创建AOP的目标源
- TargetSource targetSource = createTargetSource(this.target);
- proxyFactory.setTargetSource(targetSource);
- if (this.proxyInterfaces != null) {
- proxyFactory.setInterfaces(this.proxyInterfaces);
- }
- else if (!isProxyTargetClass()) {
- proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass()));
- }
- this.proxy = getProxy(proxyFactory);
- }
<script></script>
Spring 已经定义了一个transctionInterceptor作为拦截器或者AOP advice的实现,在IOC容器中定义的其他属性比如transactionManager和事务管理的属性都会传到已经定义好的 TransactionInterceptor那里去进行处理。以上反映了基本的Spring AOP的定义过程,其中pointcut和advice都已经定义好,同时也通过通知器配置到ProxyFactory中去了。
下面让我们回到TransactionProxyFactoryBean中看看TransactionAttributeSourceAdvisor是怎样定义的,这样我们可以理解具体的属性是怎样起作用,这里我们分析一下类TransactionAttributeSourceAdvisor:
- public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {
- //和其他Advisor一样,同样需要定义AOP中的用到的Interceptor和Pointcut
- //Interceptor使用传进来的TransactionInterceptor
- //而对于pointcut,这里定义了一个内部类,参见下面的代码
- private TransactionInterceptor transactionInterceptor;
- private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();
- .........
- //定义的PointCut内部类
- private class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
- .......
- //方法匹配的实现,使用了TransactionAttributeSource类
- public boolean matches(Method method, Class targetClass) {
- TransactionAttributeSource tas = getTransactionAttributeSource();
- //这里使用TransactionAttributeSource来对配置属性进行处理
- return (tas != null && tas.getTransactionAttribute(method, targetClass) != null);
- }
- ........省略了equal,hashcode,tostring的代码
- }
<script></script>
这里我们看看属性值是怎样被读入的:AbstractFallbackTransactionAttributeSource负责具体的属性读入任务,我们可以有两种读入方式,比如annotation和直接配置.我们下面看看直接配置的读入方式,在Spring中同时对读入的属性值进行了缓存处理,这是一个decorator模式:
- public final TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
- //这里先查一下缓存里有没有事务管理的属性配置,如果有从缓存中取得TransactionAttribute
- Object cacheKey = getCacheKey(method, targetClass);
- Object cached = this.cache.get(cacheKey);
- if (cached != null) {
- if (cached == NULL_TRANSACTION_ATTRIBUTE) {
- return null;
- }
- else {
- return (TransactionAttribute) cached;
- }
- }
- else {
- // 这里通过对方法和目标对象的信息来计算事务缓存属性
- TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
- //把得到的事务缓存属性存到缓存中,下次可以直接从缓存中取得。
- if (txAtt == null) {
- this.cache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
- }
- else {
- ...........
- this.cache.put(cacheKey, txAtt);
- }
- return txAtt;
- }
- }
<script></script>
别急,基本的处理在computeTransactionAttribute()中:
- private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {
- //这里检测是不是public方法
- if(allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
- return null;
- }
- Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
- // First try is the method in the target class.
- TransactionAttribute txAtt = findTransactionAttribute(findAllAttributes(specificMethod));
- if (txAtt != null) {
- return txAtt;
- }
- // Second try is the transaction attribute on the target class.
- txAtt = findTransactionAttribute(findAllAttributes(specificMethod.getDeclaringClass()));
- if (txAtt != null) {
- return txAtt;
- }
- if (specificMethod != method) {
- // Fallback is to look at the original method.
- txAtt = findTransactionAttribute(findAllAttributes(method));
- if (txAtt != null) {
- return txAtt;
- }
- // Last fallback is the class of the original method.
- return findTransactionAttribute(findAllAttributes(method.getDeclaringClass()));
- }
- return null;
- }
<script></script>
经过一系列的尝试我们可以通过findTransactionAttribute()通过调用findAllAttribute()得到TransactionAttribute的对象,如果返回的是null,这说明该方法不是我们需要事务处理的方法。
在完成把需要的通知器加到ProxyFactory中去的基础上,我们看看具体的看事务处理代码怎样起作用,在TransactionInterceptor中:
- public Object invoke(final MethodInvocation invocation) throws Throwable {
- //这里得到目标对象
- Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);
- //这里同样的通过判断是否能够得到TransactionAttribute来决定是否对当前方法进行事务处理,有可能该属性已经被缓存,
- //具体可以参考上面对getTransactionAttribute的分析,同样是通过TransactionAttributeSource
- final TransactionAttribute txAttr =
- getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);
- final String joinpointIdentification = methodIdentification(invocation.getMethod());
- //这里判断我们使用了什么TransactionManager
- if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
- // 这里创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去
- TransactionInfo txInfo = createTransactionIfNecessary(txAttr, joinpointIdentification);
- Object retVal = null;
- try {
- retVal = invocation.proceed();
- }
- catch (Throwable ex) {
- // target invocation exception
- completeTransactionAfterThrowing(txInfo, ex);
- throw ex;
- }
- finally {
- cleanupTransactionInfo(txInfo);
- }
- commitTransactionAfterReturning(txInfo);
- return retVal;
- }
- else {
- // 使用的是Spring定义的PlatformTransactionManager同时实现了回调接口,我们通过其回调函数完成事务处理,就像我们使用编程式事务处理一样。
- try {
- Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
- new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
- //同样的需要一个TransactonInfo
- TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
- try {
- return invocation.proceed();
- }
- .....这里省去了异常处理和事务信息的清理代码
- });
- ...........
- }
- }
<script></script>
这里面涉及到事务的创建,我们可以在TransactionAspectSupport实现的事务管理代码:
- protected TransactionInfo createTransactionIfNecessary(
- TransactionAttribute txAttr, final String joinpointIdentification) {
- // If no name specified, apply method identification as transaction name.
- if (txAttr != null && txAttr.getName() == null) {
- txAttr = new DelegatingTransactionAttribute(txAttr) {
- public String getName() {
- return joinpointIdentification;
- }
- };
- }
- TransactionStatus status = null;
- if (txAttr != null) {
- //这里使用了我们定义好的事务配置信息,有事务管理器来创建事务,同时返回TransactionInfo
- status = getTransactionManager().getTransaction(txAttr);
- }
- return prepareTransactionInfo(txAttr, joinpointIdentification, status);
- }
<script></script>
首先通过TransactionManager得到需要的事务,事务的创建根据我们定义的事务配置决定,在 AbstractTransactionManager中给出一个标准的创建过程,当然创建什么样的事务还是需要具体的 PlatformTransactionManager来决定,但这里给出了创建事务的模板:
- public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
- Object transaction = doGetTransaction();
- ......
- if (definition == null) {
- //如果事务信息没有被配置,我们使用Spring默认的配置方式
- definition = new DefaultTransactionDefinition();
- }
- if (isExistingTransaction(transaction)) {
- // Existing transaction found -> check propagation behavior to find out how to behave.
- return handleExistingTransaction(definition, transaction, debugEnabled);
- }
- // Check definition settings for new transaction.
- //下面就是使用配置信息来创建我们需要的事务;比如传播属性和同步属性等
- //最后把创建过程中的信息收集起来放到TransactionStatus中返回;
- if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
- throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
- }
- // No existing transaction found -> check propagation behavior to find out how to behave.
- if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
- throw new IllegalTransactionStateException(
- "Transaction propagation 'mandatory' but no existing transaction found");
- }
- else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
- definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
- definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
- //这里是事务管理器创建事务的地方,并将创建过程中得到的信息放到TransactionStatus中去,包括创建出来的事务
- doBegin(transaction, definition);
- boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
- return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
- }
- else {
- boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
- return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
- }
- }
<script></script>
接着通过调用prepareTransactionInfo完成事务创建的准备,创建过程中得到的信息存储在TransactionInfo对象中进行传递同时把信息和当前线程绑定;
- protected TransactionInfo prepareTransactionInfo(
- TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
- TransactionInfo txInfo = new TransactionInfo(txAttr, joinpointIdentification);
- if (txAttr != null) {
- .....
- // 同样的需要把在getTransaction中得到的TransactionStatus放到TransactionInfo中来。
- txInfo.newTransactionStatus(status);
- }
- else {
- .......
- }
- // 绑定事务创建信息到当前线程
- txInfo.bindToThread();
- return txInfo;
- }
<script></script>
将创建事务的信息返回,然后看到其他的事务管理代码:
- protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
- if (txInfo != null && txInfo.hasTransaction()) {
- if (logger.isDebugEnabled()) {
- logger.debug("Invoking commit for transaction on " + txInfo.getJoinpointIdentification());
- }
- this.transactionManager.commit(txInfo.getTransactionStatus());
- }
- }
<script></script>
通过transactionManager对事务进行处理,包括异常抛出和正常的提交事务,具体的事务管理器由用户程序设定。
- protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
- if (txInfo != null && txInfo.hasTransaction()) {
- if (txInfo.transactionAttribute.rollbackOn(ex)) {
- ......
- try {
- this.transactionManager.rollback(txInfo.getTransactionStatus());
- }
- ..........
- }
- else {
- .........
- try {
- this.transactionManager.commit(txInfo.getTransactionStatus());
- }
- ...........
- }
- protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
- if (txInfo != null && txInfo.hasTransaction()) {
- ......
- this.transactionManager.commit(txInfo.getTransactionStatus());
- }
- }
<script></script>
Spring通过以上代码对transactionManager进行事务处理的过程进行了AOP包装,到这里我们看到为了方便客户实现声明式的事务处理,Spring还是做了许多工作的。如果说使用编程式事务处理,过程其实比较清楚,我们可以参考书中的例子:
- TransactionDefinition td = new DefaultTransactionDefinition();
- TransactionStatus status = transactionManager.getTransaction(td);
- try{
- ......//这里是我们的业务方法
- }catch (ApplicationException e) {
- transactionManager.rollback(status);
- throw e
- }
- transactionManager.commit(status);
- ........
<script></script>
我们看到这里选取了默认的事务配置DefaultTransactionDefinition,同时在创建事物的过程中得到TransactionStatus,然后通过直接调用事务管理器的相关方法就能完成事务处理。
声明式事务处理也同样实现了类似的过程,只是因为采用了声明的方法,需要增加对属性的读取处理,并且需要把整个过程整合到Spring AOP框架中和IoC容器中去的过程。
下面我们选取一个具体的transactionManager - DataSourceTransactionManager来看看其中事务处理的实现:
同样的通过使用AbstractPlatformTransactionManager使用模板方法,这些都体现了对具体平台相关的事务管理器操作的封装,比如commit:
- public final void commit(TransactionStatus status) throws TransactionException {
- ......
- DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
- if (defStatus.isLocalRollbackOnly()) {
- ......
- processRollback(defStatus);
- return;
- }
- .......
- processRollback(defStatus);
- ......
- }
- processCommit(defStatus);
- }
<script></script>
通过对TransactionStatus的具体状态的判断,来决定具体的事务处理:
- private void processCommit(DefaultTransactionStatus status) throws TransactionException {
- try {
- boolean beforeCompletionInvoked = false;
- try {
- triggerBeforeCommit(status);
- triggerBeforeCompletion(status);
- beforeCompletionInvoked = true;
- boolean globalRollbackOnly = false;
- if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
- globalRollbackOnly = status.isGlobalRollbackOnly();
- }
- if (status.hasSavepoint()) {
- ........
- status.releaseHeldSavepoint();
- }
- else if (status.isNewTransaction()) {
- ......
- doCommit(status);
- }
- .........
- }
<script></script>
这些模板方法的实现由具体的transactionManager来实现,比如在DataSourceTransactionManager:
发表评论
-
CronTrigger Tutorial
2010-10-28 15:48 871CronTrigger Tutorial Introducti ... -
Spring定时器配置详解(附demo)
2010-09-13 09:17 1743http://www.mkyong.com/spring/sp ... -
Spring源代码解析(五):Spring AOP获取Proxy
2008-11-12 14:27 1377下面我们来看看Spring的A ... -
Spring源代码解析(四):Spring MVC
2008-11-12 14:26 1101下面我们对Spring MVC框架代码进行分析,对于webAp ... -
Spring源代码解析(三):Spring JDBC
2008-11-12 14:25 1035下面我们看看Spring JDBC相关的实现, 在Spring ... -
Spring源代码解析(二):IoC容器在Web容器中的启动
2008-11-12 14:23 992上面我们分析了IOC容器 ... -
Spring源代码解析(一):IOC容器
2008-11-12 14:21 1048在认真学习Rod.Johnson的三部曲之一:<< ... -
spring的applicationContext.xml中使用属性文件*.properties
2008-11-07 09:47 1827我们可以生成如下的属性文件(/WEB-INF/jdbc.pro ... -
Spring XML配置的12个技巧
2008-11-06 15:28 928Spring是一个强有力的java程序框架,其被广泛应用于j ... -
spring的IoC容器的执行流程
2008-11-06 11:16 2529应用程序的启动 main() 创建IoC容器的代表 ... -
控制反转/依赖注入
2008-11-06 10:18 1974IOC(DI):其实这个Sprin ... -
Bean 装配
2008-11-03 15:36 953Spring 容器内拼凑Bean 叫做装配。 Bean 装配要 ... -
spring2.5注释驱动的IOC功能
2008-10-31 14:06 951概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分 ... -
spring的IoC容器
2008-10-28 13:54 1300使用Spring的IoC容器 3.1 BeanFactory ...
相关推荐
Spring源代码解析6:Spring声明式事务处理 .doc Spring源代码解析7:Spring AOP中对拦截器调用的实现 .doc Spring源代码解析8:Spring驱动Hibernate的实现.doc Spring源代码解析9:Spring Acegi框架鉴权的实现.doc ...
Spring源代码解析6:Spring声明式事务处理 ; Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代码解析9:Spring Acegi框架鉴权的实现 Spring源...
Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 ...
在整个源代码分析中,我们可以看到 Spring 实现声明式事务管理有三个部分: 1. 对在上下文中配置的属性的处理,这里涉及的类是 TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性...
pring源代码解析1:IOC容器;Spring源代码解析2:IoC...Spring源代码解析6:Spring声明式事务处理 ; Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代
5. **事务管理**:"spring源代码解析(六):spring声明式事物处理.doc"分析了Spring如何提供声明式事务管理,包括@Transactional注解的工作原理和事务传播行为。 6. **Spring与Hibernate集成**:"spring源代码解析...
Spring源代码解析(六):Spring声明式事务处理.doc Spring源代码解析(七):Spring AOP中对拦截器调用的实现.doc Spring源代码解析(八):Spring驱动Hibernate的实现.doc Spring源代码解析(九):Spring Acegi...
《Spring源代码解析》 Spring框架作为Java领域最流行的开源框架之一,它的设计思想和实现方式一直是广大开发者关注的焦点。深入理解Spring的源代码,能够帮助我们更好地掌握其工作原理,提高我们的开发效率和代码...
在这个"spring声明式事务处理demo"中,我们将探讨如何在MyEclipse环境下实现这一功能。 首先,我们要理解Spring事务管理的两种主要方式:编程式事务管理和声明式事务管理。编程式事务管理通常通过AOP(面向切面编程...
Spring框架是Java开发中最常用的轻量级框架之一,它的核心特性包括依赖注入(Dependency Injection,DI)、面向切面编程(Aspect-Oriented Programming,AOP)以及声明式事务管理等。这个“Spring源代码解析”压缩包...
本资源包含两个文件:“Spring声明式事务处理.wrf”和“testtrans”,很可能是示例代码或者测试用例,用于演示如何在Java应用中使用Spring进行声明式事务处理。 首先,让我们深入理解声明式事务处理的概念。声明式...
它提供了声明式事务管理,使得事务处理更加简单。例如,`@Transactional`注解可以方便地进行事务控制。 6. **Spring Boot**: Spring Boot简化了Spring应用程序的启动和配置,通过自动配置和起步依赖,让开发者...
总的来说,Spring 3和Hibernate 4结合使用声明式事务管理,使得我们无需在代码中显式调用事务开始、提交和回滚,而是通过注解和配置文件来声明事务的边界和行为。这种方式降低了代码的复杂度,提高了可维护性和可...
在Spring框架中,声明式事务管理是实现事务处理...在博文"Spring使用XML配置声明式事务"中,作者详细讲解了每个步骤,并可能通过示例代码展示了如何实际应用这些配置,帮助读者更好地理解和掌握Spring声明式事务管理。
Spring提供了声明式事务管理,允许我们在不直接编写事务控制代码的情况下,通过配置实现事务的回滚和提交。`PlatformTransactionManager`接口和相关的事务策略类是事务管理的核心。通过源码分析,我们可以理解Spring...