0

First lets consider that we have CustomerRegister service that simply do its job.

@Service
class CustomerRegister {
    private final CustomerRegister customerRegister;

    CustomerRegister(CustomerRegister customerRegister) {
        this.customerRegister = customerRegister;
    }

    @Transactional
    public void create(Customer customer) {
        customerRegister.persist(customer);
    }
}

Later it was decided that it could be good to have a business metric about that registry operation. The common choice is to use org.springframework.boot.actuate.metrics.CounterService

Note that:

Using @Transactional, Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating

If we decide to invoke

counterService.increment(REGISTY_METRIC);

within scope of create method then counter will be increased even in transaction was rollback.

My idea is to create an aspect that wraps that transactional proxy (which wrapping original CustomerRegister service). That @Aspectcomponent could then provides method annotated with @AfterReturning(pointcut = that increment metric counter.

Other words:

  1. How to implement aspect over another aspect?
  2. How to implement aspect over transactional proxy?
Karol Król
  • 3,320
  • 1
  • 34
  • 37

1 Answers1

2

Implement the aspect as it is done normally. Just ensure the custom aspects' @Order is set to low value (i.e. highest precedence e.g. 1) so that it executes before any other aspect which is transaction aspect in this case.

Refer below image (reference) to understand the request flow graphically. By setting the appropriate order on the custom advisor(s) it can be made run before / after transaction advise without any special consideration.

Spring Transaction execution flow

Additional recommended read here to understand how aspect ordering is handled in Spring.

Bond - Java Bond
  • 3,972
  • 6
  • 36
  • 59