@Transactional 关于方面的建议可能吗?

发布于 2024-10-30 19:08:50 字数 2087 浏览 1 评论 0原文

我可以将 @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>

带切入点的方面:

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();
    }
}

Can I apply the @Transactional tag to an aspect advice? I'm trying to wrap all calls to the service layer (com.mycompany.app.myapp.service.*) in a transaction using aspects. My aspect is properly intercepting the calls to the service layer, but I can't figure out how to start a transaction. I thought I could apply the @Transactional tag and because I've got the tag, it'd pick it up and begin the transaction. What am I missing?

XML configuration:

<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>

Aspect w/pointcuts:

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() {};
}

The advice I'm trying to apply to my pointcuts:

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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

剧终人散尽 2024-11-06 19:08:51

下面我有一个示例,展示如何将 @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 ?您应该只标记您想要在事务中执行的业务方法。

我希望这有帮助!

Below I have an example that shows how you can use @Transactional together with your inServiceLayer() Pointcut. I have chosen to separate the normal flow from the exception flow. That is why I do not use the @Around advice.

@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;
    }
}

After a quick look on your code I have to ask why you have annotated your Pointcut with @Transactional? You should only mark your business methods that you want to be executed in a transaction with that.

I hope this helps!

带刺的爱情 2024-11-06 19:08:51

正如@Espen所说,您应该直接在业务方法上应用@Transactional,因为注释本身会导致Spring创建一个将事务应用于您的方法的方面。所以不需要手动创建aspect。

但是,如果您想将事务应用于所有服务方法以及通过这些切入点选择的任何其他内容,您应该使用 xml 配置来创建事务。 在文档中查找声明式事务管理

另外,我认为您不能将 @Transactional 应用于建议。至少它对我不起作用。

As @Espen said you should apply @Transactionalon your business methods directly as the Annotation itself causes Spring to create an Aspect that applies transactions to your method. So there is no need to create an aspect manually.

However, if you want to apply transactions to all you service methods and whatever else you selected with those pointcuts you should do use the xml configuration to create the transactions. Look for declarative transaction management in the documentation

Also I don't think you can apply @Transactional to an Advice. At least it is not working for me.

情栀口红 2024-11-06 19:08:51

Spring事务注解在运行时创建一个代理对象。因此,如果您在向服务提供建议的建议上应用事务注释,则事务将针对建议而不是服务,因为建议适用于服务的代理对象,而您的事务注释将适用于服务的代理对象。建议而不是建议的主要方法。理想情况下,您的建议不应是服务功能的扩展。这违背了代理模式的目的。

Spring transaction annotation at run time creates a proxy object. So if you apply transactional annotation on an advice which is advicing the service then the transaction will be for the advice and not for the service since the advice works on a proxy object of the service and your transactional annotation would work on a proxy object of the advice and not the main method of the advice. Ideally you should not be having an advice which is an extension of the functionality of the service. This defeats the purpose of the proxy pattern.

阪姬 2024-11-06 19:08:51

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() 的服务方法。

robgmills

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

You can use above Around advice but need to do couple of small changes.

  1. Add (propagation = Propagation.REQUIRES_NEW) to @Transactional
    in above.
  2. Add @Transactional annotation to the service method for which you have added the pointcut inServiceLayer().
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文