David
David

Reputation: 4873

How can I bindInterceptor in Google Guice when the Interceptor does not have a default constructor?

I have the following Guice module:

public class GuiceModule {
    @Override
    protected void configure() {}

    @Provides
    ClassA classA() {
        return new ClassA();
    }

    @Provides
    ClassB classB(ClassA classA) {
        ClassB classB = new ClassB(classA);
        classB.configure(123)
        classB.modify(456);
    }

    @Provides
    ClassC classC(ClassB classB) {
        return new ClassC(classB);
    }
}

I need to add the following bindInterceptor

bindInterceptor(
    inSubpackage("my.sub.package"),
    annotatedWith(MyAnnotation.class),
    classC);

I can only call bindInterceptor from the configure() method, based on Line 140 of this file.

What other options do I have besides not using @Provides methods and instead doing everything in the configure method?

Note: I don't own ClassA, ClassB, or ClassC. They all come from a third party package.

Upvotes: 1

Views: 2189

Answers (1)

Olivier Grégoire
Olivier Grégoire

Reputation: 35417

It looks like you want to inject your interceptors.

You have to write your injectors slightly differently and not use the constructor injection.

class ClassC {
  @Inject
  ClassB classB;                                         // Write all dependencies like this.
  @Inject
  void setClassB(ClassB classB) { this.classB = classB } // Or like this

  ClassC() { } // Write any constructor that you can actually instanciate manually
}

Then in your configure method:

ClassC classC = new ClassC();
requestInjection(classC);
bindInterceptor(inSubpackage("foo"), annotatedWith(Bar.class), classC);

Since you don't have access to the interceptor code, write your own that encapsulate the one you want:

class MyInterceptor implements MethodInterceptor {
  ClassC delegate;
  
  @Inject
  void inject(ClassB classB) { // If more dependencies are required, you can add them as parameter here, it'll just work. Don't add a setter per dependency.
    delegate = new ClassC(classB);
  }
  
  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    return delegate.invoke(invocation);
  }
}

Now use MyInterceptor instead of ClassC in your configure method:

MyInterceptor interceptor = new MyInterceptor();
requestInjection(interceptor);
bindInterceptor(inSubpackage("foo"), annotatedWith(Bar.class), interceptor);

Upvotes: 4

Related Questions