拦截春季交易的最佳方法是什么?

时间:2017-12-14 20:31:35

标签: java spring spring-boot spring-aop spring-transactions

我想在Spring Boot中分析和跟踪事务。

目前我在@Before注释上使用@Transactional方面,然后使用TransactionSynchronizationAdapter注册提交挂钩。但这不包括使用程序化api开始的任何交易(例如PlatformTransactionManager)。

我尝试在@Before("execution(* org.springframework.transaction.PlatformTransactionManager.getTransaction(..))")上设置方面切入点,但是doesn't seem to work

春天推荐的方法是什么?理想情况下使用基于注释的配置?

这是我到目前为止所做的:

@Aspect
@Component
@ConditionalOnProperty("transaction.metrics.enabled")
public class TransactionProfilerAspect {
    private static final Logger logger = LoggerFactory.getLogger(TransactionProfilerAspect.class);
    private static final AtomicLong TX_ID_FACTORY = new AtomicLong();

    @Autowired
    @Qualifier("longRunningTransactionDetectorExecutor")
    ScheduledExecutorService scheduledExecutorService;

    @Value("${transaction.metrics.timeoutMillis:5000}")
    Long transactionTimeoutMillis;

    @Before("@annotation(org.springframework.transaction.annotation.Transactional) && execution(* *(..))")
    public void beforeTransactional() {
        long txId = TX_ID_FACTORY.incrementAndGet();
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        logger.info("Starting transaction [txId={}], [txName={}]", txId, txName);

        Stopwatch stopwatch = Stopwatch.createStarted();
        ScheduledFuture<?> future = scheduleTransactionTimeout(txId, stopwatch);
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void beforeCommit(boolean readOnly) {
                logger.info("Attempting commit for [txId={}]", txId);
            }

            @Override
            public void afterCommit() {
                logger.info("Commit successful for [txId={}]", txId);
            }

            @Override
            public void afterCompletion(int status) {
                if (status == STATUS_ROLLED_BACK) {
                    logger.warn("Rolling back transaction [txId={}]", txId);
                }

                synchronized (stopwatch) {
                    if (!future.isDone()) {
                        future.cancel(true);
                    }
                }

                long elapsed = stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
                logger.info("Completed transaction [txId={}], took {}ms", txId, elapsed);
            }
        });
    }

    private ScheduledFuture<?> scheduleTransactionTimeout(long txId, Stopwatch stopwatch) {
        return scheduledExecutorService.schedule(() -> {
            synchronized (stopwatch) {
                logger.warn("Transaction [txId={}] exceeded the time limit of {}ms", txId, transactionTimeoutMillis);
            }
        }, transactionTimeoutMillis, TimeUnit.MILLISECONDS);
    }
}

0 个答案:

没有答案