I am new to spring Boot and i was trying to learn the differences between different dependency injection techniques.
Is there any scenario where dependency injection through field is always prefered over constructor or setter injection?
I read that field injection is always a bad practice.
If its bad then why we still do it?
Short answer: there is no info about that.
Long answer:
It's strange that spring docs don't even mention field injection in any way
DI exists in two major variants, Constructor-based dependency
injection and Setter-based dependency injection.
I haven't found any info about when field injection is preferred over two aforementioned ones, besides the time where you do not need any of the benefits of CBDI and SBDI(for example, easier testing and NPE avoidance) and you want to keep your code short, but even this argument becomes obsolete if you use Lombok. Why does this feature even exist in the first place, IMHO:
1.There was a bad design choice that lead to it's creation and use in production(Spring Framework's first version was published back in 2002 and probably there was no any debate about whether or not field injection is a bad practice at that time)
2.Backward-compatibility stopped from removing this feature because it could break already existing codebase.
Related
Modern Spring recommendations (Spring 4.x onwards) recommend not using field injection (with #Autowired or #Inject), and instead preferring constructor arguments. Several discussions about this here, here and the Spring Framework itself recommends constructor-based DI for mandatory dependencies.
In general I agree perfectly with the rationale, and in fact I haven't used any of the field injection mechanisms for years now.
What is bugging me however is the way we inject Spring Data Repositories. Of course these are mandatory dependencies, the service needs them to work. When one looks at the Spring Data documentation one finds that the reference documentation itself is using #Autowired field injection all over the place, precisely what was recommended as bad practice in the Spring Framework documentation itself.
Of course, it is no problem to have repositories use constructor injection. I have been using this for quite some time. However, sometimes components and services need quite a number of repositories. A service might be interacting with 7 or 8 database tables, and they would need to be in the same transaction.
How does one go about this to have neat code? Using constructor arguments is the safer approach, but leads you to have a huge number of constructor arguments. Setter injection does not seem to fit, these are not optional dependencies. Field injection is supposed to be plain wrong (even though the Spring Data doc uses it).
Is there any other approach one could use? I was tempted to aggregate related repositories in a separate #Component, at least the service constructor gets only one argument with this constructor. It does help a bit, but makes it even harder to interact with a new table (the new repository would need to be added to the aggregate, and the service would need to call the getter for it).
How is it supposed to be done neatly without violating any safety recommendations and adhering to coding standards (few constructor arguments etc.)?
I am new to Spring can anyone tell me What is difference between autowiring vs dependency injection in Spring ?
I tried to search on internet but I dont find things much helpful.
There is no difference. When the concept was new, there were several names used, and "dependency injection" ended up becoming the most common. Spring's configuration system used "autowire", and that's stuck around there, and the GoF term "inversion of control" is sometimes used, usually in a more academic setting. They're all synonyms.
Using Spring dependency injection it is possible to swap out a dependency at run time by tweaking the XML file.
I don't think this is possible using the Scala cake pattern dependency injection since the dependencies are wired at compile time and to change the dependencies would require re-compilation ?
If so is this an advantage that Spring dependency injection has over using the Scala cake pattern for dependency injection ?
Yes using the cake pattern you will need to recompile. The whole point of the cake pattern is to do compile time dependency injection :)
With spring you will return to "classic" (in java world) runtime dependency injection, which is done through reflection.
Using runtime dependency injection, you might be able to swap out a dependency at runtime either by restarting the whole container or by using specific modules like jrebel to update only part of the context. In exchange you pay the price at application startup as your container has to parse the XML, instanciate all the objects and wire them up. In the case of spring the wiring can be fairly complex requiring multiple passes to complete.
Usually you don't want to swap out dependencies at runtime in production code (there are valid use cases for this but I have rarely encountered them).
On the other hand, the cake pattern is validated at compile time, the wiring is necessarily predetermined (forget about #PostConstruct). Avoiding complex wiring cycles is actually a good thing :) You will also avoid loading and parsing XML files (though in my understanding the current preferred configuration method is using code not XML). Errors in the wiring will appear sooner in cake giving you a quicker feedback.
Last but not least, there are other DI mechanisms available in functionnal programming languages (such as scala) such as using an IO or a Reader Monad. For more about such mechanisms you can start at :
http://blog.originate.com/blog/2013/10/21/reader-monad-for-dependency-injection/
http://fr.slideshare.net/debasishg/dependency-injection-in-scala-beyond-the-cake-pattern
or
Using Reader Monad for Dependency Injection
I'm a newbie to Spring Framework and of course first thing comes to mind about spring is dependency injection. Now i could be wrong since i just started learning about Spring framework (esp. about dependency injection) but i think that dependency injection of beans to said objects is not meant for transaction data. Since the bean definition is for example defined in the spring.xml (a blue print) it is not meant for transactional data but rather for static and small amount of data. I don't see that there's any way to inject thousands of transactional objects into another object using dynamic XML (created during runtime).
So did i get this right? If that is so what's the real benefit of dependency injection?
There are several benefits from using dependency injection containers rather than having components satisfy their own dependencies. Some of these benefits are:
Reduced Dependencies
Reduced Dependency Carrying
More Reusable Code
More Testable Code
More Readable Code
These benefits are explained in more detail here.
You are right, transactional data (eg: data that represents a table row) don't normally be injected declaratively. Spring DI (dependency injection) commonly use to handle collaboration between multiple classes.
Common examples I've seen is along with DAO (data access object) and MVC (model view controller) pattern. In enterprise environment it's common to have a project with dozens or hundreds of database tables -- hence dozens / hundreds of DAO classes which get injected into controller classes.
If you don't use DI, you need to conciously manage which DAO should be created first, and which DAO should be injected into which controller etc. (this is a nightmare)
Code refactoring is (should) be a common thing as well. Business requirement always changes constantly. Without DI one simple refactoring could result in a massive and tricky untangling of 'which class depends on what and where'
Of all the articles I've read about the dependency injection, this is by far the best.
If you are using Spring for DI, I would suggest you read about #primary annotation. Spring makes it even easier to choose the implementation you want(from multiple implementations) for a given service. This article is good.
Dependency Injection and Inversion of Control change the control flow adding to a specific component the responsibility to manage de dependency graph and manage how it will be connected. The result is a great decoupling between dependant and dependency, improving the code maintainability, application reliability, and testability.
As far as I understand, main purpose of dependency injection is to have all dependencies separated declaratively, so that we can easily review and change the dependency structure easily...right?
Then by using dependency annotations spread through out the code, aren't we just going back to non-centralized system (similar to simple new operator), which is harder to tweak?
#Autowired/#Inject annotations usually declare dependencies on interfaces rather than on concrete classes (as in the case of new), thus you still can control which implementations should be injected by controlling which beans are declared in the context. Also, these dependencies can be overriden manually.
#Component-family annotations can be controlled as well, since you can exclude particular classes from component scanning.
The purpose of dependency injection is to decouple the declaration of dependencies from the actual satisfying of those dependencies. How the declaration is done is an orthogonal issue.
#Autowired is a form of dependency declaration. Using #Autowired supports encapsulation. A class' injected dependencies are documented directly in the code instead of in another file.
These types of discussions have tendency to become religious so I'll stear clear of the "main purpose" definition and the semantics of whether this or that pattern is really and truly fulfilled.
I try to look at it like a tool that can offer certain features. For instance, using Spring (DI) is a good way to separate interfaces and implementations. Users of a particular interface need not know how to create the implementation (or where it resides). This is often something good. Using Spring also enables a whole lot of other stuff: AOP and AOP-driven features like transaction handling, scopeing and a whole bunch of pre-built integrations to other frameworks and technologies. Annotations make a lot of this easier and clearer and best of all, I don't have to use them where it's not practical or possible - there is always the option to configure it in XML instead.