Spring中的@Transactional(AOP)

lev*_*eep 10 java hibernate transactions spring-aop

我创建了一个包含@Transactional注释的Aspect.我的建议正在按预期调用,但新实体AuditRecord永远不会保存到数据库中,看起来我的@Transactional注释不起作用.

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

}
Run Code Online (Sandbox Code Playgroud)

bean上下文如下:

<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>
Run Code Online (Sandbox Code Playgroud)

我的切入点只拦截接口(服务接口).服务方法可能是也可能不是交易方式.如果服务方法是事务性的,我希望如果Advice由于某种原因失败,则回滚该事务.

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

谢谢!

Fed*_*ner 17

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

只需将createRecord方法移动到一个新类(不要忘记使它成为一个Spring bean)它会起作用.