Java – Dependency Injection: Field Injection vs Constructor Injection

dependency-injectionjavajava-ee

I know this is a hot debate and the opinions tend to change over time as to the best approach practice.

I used to use exclusively field injection for my classes, until I started reading up on different blogs (exs: petrikainulainen and schauderhaft and fowler) about the benefits of constructor injection. I have since switched my methodologies to use constructor injection for required dependencies and setter injection for optional dependencies.

However, I have recently gotten into a debate with the author of JMockit – a mocking framework – in which he sees constructor & setter injection as bad practice and indicates that the JEE community agrees with him.

In today's world, is there a preferred way of doing injection? Is Field injection preferred?

Having switched to constructor inject from field injection in the last couple of years, I find it a lot clearer to use, but I am wondering if I should re-examine my viewpoint. The author of JMockit (Rogério Liesenfeld), is clearly well versed in DI, so I feel obligated to review my approach given that he feels so strongly against constructor/setter injection.

Best Answer

Field injection is a bit too "spooky action at a distance" for my taste.

Consider the example you provided in your Google Groups post:

public class VeracodeServiceImplTest {


    @Tested(fullyInitialized=true)
    VeracodeServiceImpl veracodeService;
    @Tested(fullyInitialized=true, availableDuringSetup=true)
    VeracodeRepositoryImpl veracodeRepository;
    @Injectable private ResultsAPIWrapper resultsApiWrapper;
    @Injectable private AdminAPIWrapper adminApiWrapper;
    @Injectable private UploadAPIWrapper uploadApiWrapper;
    @Injectable private MitigationAPIWrapper mitigationApiWrapper;

    static { VeracodeRepositoryImpl.class.getName(); }
...
}

So basically what you are saying is that "I have this class with private state, to which I have attached @injectable annotations, which means that the state can be automagically populated by some agent from the outside, even though my state has all been declared private."

I understand the motivations for this. It is an attempt to avoid much of the ceremony that is inherent in setting up a class properly. Basically, what one is saying is that "I'm tired of writing all of this boilerplate, so I'm just going to annotate all of my state, and let the DI container take care of setting it for me."

It's a perfectly valid point of view. But it's also a workaround for language features that arguably should not be worked around. Also, why stop there? Traditionally, DI has relied on each class having a companion Interface. Why not eliminate all those interfaces with annotations as well?

Consider the alternative (this is going to be C#, because I know it better, but there's probably an exact equivalent in Java):

public class VeracodeService
{        
    private readonly IResultsAPIWrapper _resultsApiWrapper;
    private readonly IAdminAPIWrapper _adminApiWrapper;
    private readonly IUploadAPIWrapper _uploadApiWrapper;
    private readonly IMitigationAPIWrapper _mitigationApiWrapper;

    // Constructor
    public VeracodeService(IResultsAPIWrapper resultsApiWrapper, IAdminAPIWrapper adminApiWrapper, IUploadAPIWrapper uploadApiWrapper,         IMitigationAPIWrapper mitigationApiWrapper)
    {
         _resultsAPIWrapper = resultsAPIWrapper;
         _adminAPIWrapper = adminAPIWrapper;
         _uploadAPIWrapper = uploadAPIWrapper;
         _mitigationAPIWrapper = mitigationAPIWrapper;
    }
}

Already I know some things about this class. It's an immutable class; state can only be set in the constructor (references, in this particular case). And because everything derives from an interface, I can swap out implementations in the constructor, which is where your mocks come in.

Now all my DI container has to do is reflect over the constructor to determine what objects it needs to new up. But that reflection is being done on a public member, in a first-class way; i.e. the metadata is already part of the class, having been declared in the constructor, a method whose express purpose is to provide the class with the dependencies it needs.

Granted this is a lot of boilerplate, but this is how the language was designed. Annotations seem like a dirty hack for something that should have been built into the language itself.