4

I know my title is confusing. Im having a hard time to summarize what I want to ask. What I mean is is there a way to use guice to inject classes that implement interface A using a binding method where the annotation is in the class that implements interface A rather than binding it in the configure method or adding a @ImplementedBy annotation in interface A.

Update

As I read tutorials using guice, in order to dictate that a certain class implements an interface one must use bindings. Now there are many ways to perform bindings. Examples of which are: Linked Binding:

bind(AInterface).to(Bclass); 

This code will be located in the configure method of the class that extends abstract module. This tells guice that if their are dependencies that require AInterface it may inject BClass to handle to dependency.

Just in time binding:

@ImplementedBy(BClass.class)
public interface AInterface {
}

This example is equivalent to the linked binding example.

Now all of the bindings I read require me to declare in either the configure method or interface that a class implements that interface. This will require me to edit existing code every time I implement the interface. What I want is to simply have the class that implements the interface handle the binding itself so as not to modify existing code.

Something like

@Exports(AInterface.class)
public BClass implements AInterface{
}
MykelXIII
  • 1,085
  • 1
  • 8
  • 16
  • Could you elaborate? Perhaps post some code examples showing what you want to do (pseudo-code or code that won't compile would be ok if it show the intent) – Peter Svensson Jan 29 '14 at 08:25
  • I have updated my question. I hope it is clearer now. – MykelXIII Jan 29 '14 at 08:38
  • I don't think you can do that, there can be many implementations of `AInterface` so which one is annotated, what if two are annotated, ... Also, your `BClass` should explicitly implements `AInterface` –  Jan 29 '14 at 09:07
  • Sorry forgot to explicitly implement. I am aware that there can be many implementations. I just feel that it would be a hassle updating existing code if i decide to use a different implementation. But if there is no other way then I guess I have no choice. – MykelXIII Jan 29 '14 at 09:11
  • To change the implementation: Normal way, you change the existing `bind` ; Your way, you remove the annotation from the existing one (that's existing code!) and add it to a new implementation. I don't see any difference in difficulty or quantity of work –  Jan 29 '14 at 10:24

1 Answers1

1

There's no way to do this.

As RC noted in the comments, if you have two classes that both "@Exports" the same interface, Guice wouldn't know which one to pick. Furthermore, consider it from the class-loading perspective:

  • Explicit bindings (either linked or untargeted) work because the Module explicitly refers to every class it binds, which allows Guice to find those classes.
  • JIT bindings work because they ask for the specific class they implement, which also allows Guice to find those classes.
  • @ImplementedBy annotations work because once the class requested has been loaded, it points to the implementation, so Guice knows how to find that class.

If one were to write an @Exports annotation, Guice would effectively have to have already found BClass in order to recognize that it offers AInterface, despite no explicit reference to BClass anywhere. Though class-path scanning solutions exist, they have to mill through every class on the classpath, which takes some time and would be a dangerous thing for Guice to do silently. Therefore, it makes the most sense to require some kind of explicit binding for the case you're looking for.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • http://stackoverflow.com/questions/6085200/how-to-get-all-implementors-subclasses-of-an-interface-with-guice/40558788#40558788 describes a vaguely related way how to auto-detect AInterface by looking at BClass which probably could be used to come up with something to write something automagical as sought above IFF BClass was already wired elsewhere anyway. – vorburger Nov 12 '16 at 01:57