1

I have two different aspects. How do I ensure that when calling method from one aspect, it will still go through proxy chain?

Here is relevant code:

Inner aspect:

@Around("withinReplicatedRepository() && entityMethod() && insertMethod()")
public Object trackInsert(ProceedingJoinPoint jp) throws Throwable {
    return trackChange(jp, ChangeType.INSERT, jp.getArgs()[0]);
}

Outer aspect:

@Around("withinReplicatedRepository() && entityMethod() && autoSaveRepository() && saveMethod()")
public Object saveEntity(ProceedingJoinPoint jp) throws Throwable {
    TransactionUtil.ensureTransactional();

    Object entity = jp.getArgs()[0];
    AutoSaveRepository repository = (AutoSaveRepository)jp.getTarget();
    if (repository.exists(entity)) {
        repository.update(entity);
    } else {
        repository.insert(entity);
    }
    return null;
}

Usage:

AutoSaveRepository<MyEntity> repo = ...;
repo.save(entity);

My problem is that jp.getTarget() will return original class, thus repository.insert() will not be captured by trackInsert.

Sasa
  • 1,597
  • 4
  • 16
  • 33
  • What is `...` in `AutoSaveRepository repo = ...;`? Is `AutoSaveRepository` a singleton bean? Then it should be easy to get the bean for this using `getBean(..)`. – kriegaex Mar 29 '18 at 03:00
  • It is not singleton, there are multiple instances of AutoSaveRepository. – Sasa Mar 29 '18 at 07:29

1 Answers1

4

You can try

AopContext.currentProxy()

See Javadoc.

The prerequisite is that you activate proxy exposure, though:

  • In XML you can do this since Spring 3.0.3 via
    <aop:aspectj-autoproxy expose-proxy="true"/>.
  • In annotation-style config your can do it since 4.3.1 via
    @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true),
    see Javadoc
kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • I saw that in other threads. But isn't `AopContext.currentProxy()` considered a sort of a _hack_? – Sasa Mar 29 '18 at 07:30
  • It is documented in Spring's Javadoc. What would you think? But if you have another way of getting hold of the bean instance (proxy), use that one. Alternatively, use full AspectJ with LTW and get rid of Spring's proxies. – kriegaex Mar 29 '18 at 07:49
  • It does feel a little bit like a hack (see this answer too: https://stackoverflow.com/a/7482767/353563), but if this is the only way, then I don't have much choice. Ideally, there would be method in ProceedingJoinPoint to get original object, but I understand why is that hard to achieve. – Sasa Apr 03 '18 at 07:59
  • So because one person in another answer said that it means it is a hack? Actually, Spring AOP does have its limitations. Compared to AspectJ is is rather "AOP lite", but if you do not want to switch, you have to take what is offered. :-) – kriegaex Apr 03 '18 at 14:29