2011-04-07 65 views
2

我可以将@Transactional标签应用于方面建议吗?我试图在使用方面的事务中将所有调用包装到服务层(com.mycompany.app.myapp.service。*)。我的方面正在拦截对服务层的调用,但我无法弄清楚如何启动一个事务。我以为我可以应用@Transactional标签,因为我已经有了标签,它会选择它并开始交易。我错过了什么?@交易方面的建议可能吗?

XML配置:

<bean id="systemArchitectureAspect" class="com.mycompany.app.myapp.aspect.SystemArchitecture"/> 
<bean id="transactionAspect" class="com.mycompany.app.myapp.aspect.MyAspect"/> 

<tx:annotation-driven transaction-manager="transactionManager" /> 

<bean id="transactionManager" 
    class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="transactionManager" ref="AtomikosTransactionManager" /> 
    <property name="userTransaction" ref="AtomikosUserTransaction" /> 
</bean> 

<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" 
    init-method="init" destroy-method="close"> 

    <property name="forceShutdown" value="false" /> 
</bean> 

<bean id="AtomikosUserTransaction" 
    class="com.atomikos.icatch.jta.UserTransactionImp"> 
    <property name="transactionTimeout" value="10" /> 
</bean> 

<tx:advice id="txAdvice" transaction-manager="transactionManager"> 
    <tx:attributes> 
     <tx:method name="*" propagation="REQUIRED" /> 
    </tx:attributes> 
</tx:advice> 

方面W /切入点:

package com.mycompany.app.myapp.aspect; 

@Aspect 
public class SystemArchitecture { 
    @Pointcut("execution(* com.mycompany.app.myapp.service..*.*(..))") 
    public void inServiceLayer() {}; 

    @Pointcut("execution(* com.mycompany.data..*.*(..))") 
    public void inDataAccessLayer() {}; 
} 

我想申请我的切入点建议:

package com.mycompany.app.myapp.aspect; 

@Aspect 
public class TransactionAspect { 

    @Transactional 
    @Around("com.mycompany.app.myapp.aspect.SystemArchitecture.inServiceLayer()") 
    public Object interceptServiceLayer(ProceedingJoinPoint pjp) throws Throwable 
    { 
     return pjp.proceed(); 
    } 
} 

回答

2

下面我有一个示例说明如何将@TransactionalinServiceLayer()一起使用Pointcut。我选择将正常流程与异常流程分开。这就是为什么我不使用@Around的建议。

@Aspect 
public class TransactionAspect { 
    private TransactionService transactionService = new TransactionServiceNull(); 

    @Pointcut("execution(* com.mycompany.app.myapp.service..*.*(..))") 
    public void inServiceLayer() {}; 

    @Pointcut("execution(@org.springframework.transaction.annotation 
     .Transactional * *(..))") 
    public void transactionalMethod() {} 

    @Before("transactionalMethod() && inServiceLayer()") 
    public void beforeTransactionalMethod(JoinPoint joinPoint) { 
     transactionService.beginTransaction(); 
    } 

    @AfterReturning("transactionalMethod() && inServiceLayer()") 
    public void afterTransactionalMethod(JoinPoint joinPoint) { 
     transactionService.commit(); 
    } 

    @AfterThrowing(pointcut = "transactionalMethod() && inServiceLayer()", 
     throwing = "e") 
    public void afterThrowingFromTransactionalMethod(JoinPoint joinPoint, 
     RuntimeException e) { 
     transactionService.rollback(); 
    } 

    public void setTransactionService(
     final TransactionService transactionService) { 
     this.transactionService = transactionService; 
    } 
} 

后快速浏览一下你的代码,我要问,为什么你有@Transactional注解你Pointcut?您应该只标记您希望在交易中执行的业务方法。

我希望这有助于!

+0

对不起,对于最近的回复,你给了我提示,我一直在用它来完成项目。使用@Transactional注解是最后一次希望得到它的努力。我不应该将它复制到示例代码中。谢谢您的帮助! – robgmills 2011-05-04 22:07:55

0

由于@Espen表示您应该直接在您的业务方法上应用@Transactional,因为Annotation本身导致Spring创建一个将事务应用于您的方法的方面。所以不需要手动创建一个方面。

但是,如果要将事务应用于所有服务方法以及您使用这些切入点选择的任何内容,则应该使用xml配置来创建事务。 Look for declarative transaction management in the documentation

另外我不认为你可以将@Transactional应用于建议。至少它不适合我。

0

运行时的Spring事务注释创建一个代理对象。因此,如果您在提供服务的建议上应用事务注释,那么事务将用于建议而不是用于服务,因为建议对服务的代理对象起作用,并且您的事务注释可以用于服务的代理对象建议而不是建议的主要方法。理想情况下,你不应该有一个建议,这是该服务功能的扩展。这破坏了代理模式的目的。

0

robgmills

@Transactional 
    @Around("com.mycompany.app.myapp.aspect.SystemArchitecture.inServiceLayer()") 
    public Object interceptServiceLayer(ProceedingJoinPoint pjp) throws Throwable 
    { 
     return pjp.proceed(); 
    } 

您可以使用上面围绕的意见,但需要做一些小小的变化。

  1. 添加(propagation = Propagation.REQUIRES_NEW)@Transactional 以上。
  2. @Transactional注释添加到您添加了切入点inServiceLayer()的服务方法。