首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring @Transactional in a Aspect (AOP)

Spring @Transactional in a Aspect (AOP)
EN

Stack Overflow用户
提问于 2014-12-31 03:49:57
回答 2查看 17.8K关注 0票数 16

我已经创建了一个包含@Transactional注解的方面。我的建议如预期的那样被调用,但是新的实体AuditRecord从未保存到数据库中,看起来我的@Transactional注释不起作用。

代码语言:javascript
复制
@Aspect
@Order(100)
public class ServiceAuditTrail {

private AppService appService; 
private FooRecordRepository fooRecordRepository;

@AfterReturning("execution(* *.app.services.*.*(..))")
public void logAuditTrail(JoinPoint jp){
    Object[] signatureArgs = jp.getArgs();
    String methodName = jp.getSignature().getName();

    List<String> args = new ArrayList<String>();
    for(Object arg : signatureArgs){
        args.add(arg.toString());
    }

    createRecord(methodName, args);
}

@Transactional
private void createRecord(String methodName, List<String> args){
    AuditRecord auditRecord = new AuditRecord();
    auditRecord.setDate(new Date());
    auditRecord.setAction(methodName);
    auditRecord.setDetails(StringUtils.join(args, ";"));
    auditRecord.setUser(appService.getUser());
    fooRecordRepository.addAuditRecord(auditRecord);
}

    public void setAppService(AppService appService) {
        this.appService = appService;
    }

    public void setFooRecordRepository(FooRecordRepository fooRecordRepository) {
        this.fooRecordRepository= fooRecordRepository;
    }

}

bean上下文如下所示:

代码语言:javascript
复制
<tx:annotation-driven transaction-manager="txManager.main" order="200"/>

<aop:aspectj-autoproxy />

<bean id="app.aspect.auditTrail" class="kernel.audit.ServiceAuditTrail">
    <property name="appService" ref="app.service.generic" />
    <property name="fooRecordRepository" ref="domain.repository.auditRecord" />
</bean>

我的切入点是只拦截接口(服务接口)。服务方法可能是事务性的,也可能不是事务性的。如果服务方法是事务性的,那么如果通知由于某种原因失败,我希望回滚该事务。

我的问题是:为什么事务性注释被忽略了?这是我第一次使用Spring构建AOP服务,我也欢迎任何架构或实现方面的改进。

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-31 04:01:27

在Spring中,@Transactional的工作方式是创建类的代理( Java或cglib代理)并拦截带注释的方法。这意味着,如果您从同一个类的另一个方法调用带注释的方法,则@Transactional不起作用。

只需将createRecord方法移到一个新类中(别忘了也让它成为Spring bean ),它就能工作了。

票数 24
EN

Stack Overflow用户

发布于 2014-12-31 05:21:08

这是一个非常好的问题。如果您必须回滚/提交事务,您可以直接按照前面提到的here配置spring事务。

执行此方法不需要在每个类/方法上手动添加@Transactional

Spring配置如下(从参考链接复制)。不需要编写定制的顾问/切入点,只需使用您的顾问/切入点在spring应用程序context.xml文件中添加配置即可。

代码语言:javascript
复制
<bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true"/>
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!-- ensure that the above transactional advice runs for any execution
        of an operation defined by the FooService interface -->
    <aop:config>
        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
    </aop:config>

    <!-- don't forget the DataSource -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
        <property name="username" value="scott"/>
        <property name="password" value="tiger"/>
    </bean>

    <!-- similarly, don't forget the PlatformTransactionManager -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

参考:

春季事务性

  1. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27711615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档