1

Is there a way to use Guice and AspectJ for situation where i have an aspect which have to use some complex-to-instantiate service in its logic?

For example:

@Aspect
public class SomeAspect {

  private final ComplexServiceMangedByGuice complexServiceMangedByGuice;

  @Inject
  public SomeAspect(ComplexServiceMangedByGuice complexServiceMangedByGuice){
    this.complexServiceMangedByGuice = complexServiceMangedByGuice;
  }

  @AfterThrowing(value = "execution(* *(..))", throwing = "e")
  public void afterThrowingException(JoinPoint joinPoint, Throwable e){
    complexServiceMangedByGuice.doSomething(e);
  }
}

If i try having it like in the example (with aspect constructor), my aspect will not be called. If i try injecting field (without aspect constructor defined), aspect will be called but field complexServiceMangedByGuice won't be set. One solution i have found is to get instance in advice method body, so an aspect would look like this:

@Aspect
public class SomeAspect {

private static ComplexServiceManagedByGuice complexServiceManagedByGuice;

  @AfterThrowing(value = "execution(* *(..))", throwing = "e")
  public void afterThrowingException(JoinPoint joinPoint, Throwable e){
    if(complexServiceManagedByGuice == null){
    Injector injector = Guice.createInjector(new ModuleWithComplexService());
    complexServiceMangedByGuice = injector.getInstance(ComlexServiceManagedByGuice.class);
    }
    complexServiceMangedByGuice.doSomething(e);
  }
}

But that has some undesirable overhead.

4evertoblerone
  • 95
  • 1
  • 3
  • 12
  • 1
    @OlivierGrégoire yes, i wrote it in the question.:) If i try injecting field (without aspect constructor defined), aspect will be called but field complexServiceMangedByGuice won't be set. – 4evertoblerone Feb 13 '17 at 11:50

2 Answers2

6

You can annotate fields of your aspect class like so:

@Inject
SomeDependency someDependency

Then ask Guice to inject dependencies into your aspect class by writing this in your Guice module's configure() method:

requestInjection(Aspects.aspectOf(SomeAspect.class));

The docs for requestInjection say:

Upon successful creation, the Injector will inject instance fields and methods of the given object

Source: https://github.com/jponge/guice-aspectj-sample

zAlbee
  • 1,160
  • 8
  • 9
1

This is something I have wrestled with, and I don't think there is a good answer.

The two libraries basically work against each other: The AspectJ aspects are essentially static, and Guice abhors making anything injectable be static.

I think your options are:

  • Use Guice AOP - Clean, but limited compared to AspectJ (can only weave injected classes)
  • Put the injector into a static "global" reference so the aspect can access it. (Yuck.)
  • Use some sort of thread-context (ultimately a thread-local) to communicate the injector to the aspect (Also yuck - though maybe less so)
Tim Gage
  • 1,381
  • 10
  • 19
  • 1
    Could you please elaborate on what do you mean by 'AspectJ aspects are essentially static'? – u07103 May 21 '17 at 00:41
  • While this answer makes some good points they are not solid as zAlbee answer shows there is a practical way to inject into Aspects via Guice. – Frankie Mar 07 '19 at 00:50