Lebowski
Lebowski

Reputation: 618

Spring constructor injection and super call verbosity

I started to use constructor injection in my projects since Spring declared field injection to be deprecated. Actually, the code feels prettier and more strict, I'm ok with that. But I encountered a pattern which seems a bit...weird and verbose to me:

I have an abstract service bean class (with @Service annotation), which has, say 2 dependencies, injected directly in the constructor:

@Autowired
public AbstractService(DependencyA depA, DependencyB depB) {
    this.depA = depA;
    this.depB = depB;
}

Then I have multiple services bean classes (still with @Serviceannotation) extending the abstract one. And I don't know if there is another way but this is where I find a bit verbose and repetitive having to inject the dependencies for the parent, in each sub-class constructor:

@Service
public class ServiceA extends AbstractService {
    private final DepC depC;

    @Autowired
    public ServiceA(DepA depA, DepB depB, DepC depC) {
        super(depA, depB);
        this.depC = depC;
    }

}

I just wanted to know if this is the right way, and what you think about this ?

Upvotes: 5

Views: 8599

Answers (2)

alexbt
alexbt

Reputation: 17085

The @Autowired on AbstractService doesn't do anything. Change it to:

@Service
public class ServiceA extends AbstractService {
    private final DepC depC;

    @Autowired
    public ServiceA(DepA depA, DepB depB, DepC depC) {
        super(depA, depB);
        this.depC = depC;
    }
}

...

public AbstractService(DependencyA depA, DependencyB depB) {
    this.depA = depA;
    this.depB = depB;
}

I'm ok with this setup.

For me, the main benefits of using constructor injection is to inform the developer what are the external dependencies. I find it useful when writing unit test. When writing mocks, you just know what needs to be mocked.

An other benefit is to highlight when a Class has too many dependencies, it gives a hint that refactoring may be in order.

The alternative would be using setter injection (while keeping the informational aspect), but I've grown to enjoy constructor injection.

Upvotes: 4

GhostCat
GhostCat

Reputation: 140633

My answer is focusing about the "verbose and repetitive" part in your question; I let others decide how "correct" your usage of annotations is.

Even with Spring and its DI framework, in the end we are still talking about Java source code!

And in Java, if your base class only offers a constructor that takes some A and B; then of course your subclass has to make a call super(A a, B b); and of course, those values a and b have to come from somewhere!

So, what you call "verbose and repetitive" is a direct consequence of using Java.

In other words: there is no way to avoid that part!

Upvotes: 2

Related Questions