springdependency-injectionguicejsr330

When should I use binding annotations vs more-specific interfaces?


Question

What criteria should be used when deciding between:

Example

Suppose I have:

interface FooLoader {
    Foo loadById(long id);
}

class DBFooLoader implements FooLoader {
    ... jdbc etc. etc. ...
}

class CachingFooLoader implements FooLoader {
    ...
    @Inject
    public CachingFooLoader(FooLoader delegate) {
        this.delegate = delegate;
    }
    ...
}

Suppose I want to bind FooLoader to CachingFooLoader, I have [at least] two ways to wire this:

Use an annotation binding

Change:

public CachingFooLoader(FooLoader delegate)

to:

public CachingFooLoader(@NonCaching FooLoader delegate)

and then:

bind(FooLoader.class).annotatedWith(NonCaching.class).to(DBFooLoader.class);

Create a more specific interface

Change:

public CachingFooLoader(FooLoader delegate)

to:

public CachingFooLoader(NonCachingFooLoader delegate)

where NonCachingFooLoader simply extends FooLoader, and then have DBFooLoader implement NonCachingFooLoader, and wire up accordingly.

My thoughts

I am drawn to using an annotation binding for multiple reasons:

However, creating a more specific interface has its advantages too:

So, what criteria should be used to determine which approach to take?

(Spring users, as far as I can tell, this is what you guys call qualifiers.)


Solution

  • Use specific interfaces only if it makes sense, i.e. they have to offer a different API and thus other classes will use them in a specific way.

    If they offer the same "service" in different ways, then use only one common interface and differentiate implementations with annotations.