Spring TaskExecutor事务丢失(代理与直接呼叫)

时间:2014-04-30 12:27:34

标签: spring proxy transactions

我尝试将TaskExecutor(ThreadPoolTask​​Executor)用于当前运行良好的事务服务,但是当我启动任务时,不再找到现有的事务。

(当低于start()方法时,已经有一个事务处于活动状态) (SimplePOJO不在上下文中,只保留一些数据,可以说存储在数据库中)

@Component
@Transactional(rollbackFor = { Exception.class })
public class MyService {

    @Autowired
    MyTaskRunner myTaskRunner;

    public void start() {

        // TransactionSynchronizationManager.isActualTransactionActive() -> true

        SimplePOJO pojo = new SimplePOJO();
        myTaskRunner.executeTask(pojo);
    }
}

Above Service使用此组件:

@Component
public class MyTaskRunner implements ApplicationContextAware {

    @Autowired
    private TaskExecutor taskExecutor;

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyTaskRunner.applicationContext = applicationContext;
    }

    public void executeTask(SimplePOJO simplePOJO) {

        // TransactionSynchronizationManager.isActualTransactionActive() -> true

        MyDelegate myDelegate = applicationContext.getBean(MyDelegate.class);
        myDelegate.setSimplePOJO(simplePOJO);
        taskExecutor.execute(myDelegate);
    }
}

以这种方式配置ThreadPoolTask​​Executor:

<bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="1" />
    <property name="maxPoolSize" value="5" />
    <property name="queueCapacity" value="25" />
</bean>

最终应该在每个任务的新事务中启动异步工作:

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class MyDelegate implements Runnable {

    private SimplePOJO simplePOJO;

    @Override
    public void run() {

        // TransactionSynchronizationManager.isActualTransactionActive()); -> False!

        if (this.simplePOJO != null) {
            this.doStuff(angebotAnfrageContainer);
        }
    }

    public void setSimplePOJO(SimplePOJO simplePOJO) {
        this.simplePOJO = simplePOJO;
    }

    @Async
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    private void doStuff() {

        // TransactionSynchronizationManager.isActualTransactionActive()); -> False!

        // do stuff with the pojos data in the transaction (persist on DB)
    }

}

你对我在这里缺少什么有什么建议吗?

非常感谢提前!

我尝试了什么 写上面的代码&amp;在网上搜了几个小时,这就是我发现的:

我不得不承认我对Spring很新,并且还没有很好地理解框架。在尝试和搜索网络的最后几个小时内,我认为它与从春天创建的Proxys beeing有关,当我调用execute() - Method或当TaskRunner调用run()时链断裂 - 相反的方法调用代理直接调用实现(MyDelegate)...但我绝对没有想法如何验证或更改它。

非常感谢提前

1 个答案:

答案 0 :(得分:3)

使用AOP应用交易。默认情况下,Spring使用proxies来应用AOP。代理的使用导致只有调用(外部方法调用)对象被拦截。在你的情况下,你正在从对象内部进行一个方法调用,它不会通过代理并且不会被拦截,基本上会使你的@Transactional无用。

只需将@Transactional移动到run方法即可解决您的问题,因为run方法现在将在事务中运行。

@Transactional
public void run() {...}

你也可以删除@Async,因为这里没有做任何事情,你正在执行任务TaskExecutor已经使它们异步(取决于你使用的TaskExecutor)。

链接:

  1. Understanding AOP Proxies
  2. TaskExecutor