Everybody knows that #Autowired(#Inject etc) annotation is processed by AutowiredAnnotationBeanPostProcessor. It parses and set fields and setters annotated with #Autowired but what about constructors? This is bean PostProcessor, that means that it is called after bean was already created, but constructors can also be marked as #Autowired, so how such beans are created?
Good question. For clarification's sake, to re-word it:
How does Spring provide the capability to do dependency injection on
constructor parameters when it seems like dependencies are injected
only after the bean is created?!
If you look at the AutowiredAnnotationBeanPostProcessor you'll find that there is a method called #determineCandidateConstructors that doesn't get called anywhere from inside that class itself.
The reason it's not called there is because it's referenced in the AbstractAutowireCapableBeanFactory; a class that's used for the actual creation/instantion of the bean!
I would imagine Juergen and the Spring guys decided it made architectural sense to put the #determineCandidateConstructors in the AutowiredAnnotationBeanPostProcessor class because it fits in with the concept function of the real purpose of Autowire-ing an injected dependency.
FYI, these concepts of field #Autowire vs. constructor #Autowire is so tightly tied together, that there is a whole discussion in the Spring DI world on whether to use constructor vs. dependency injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information.
Related
I read in some posts about Spring MVC and Portlets that field injection is not recommended. As I understand it, field injection is when you inject a Bean with #Autowired like this:
#Component
public class MyComponent {
#Autowired
private Cart cart;
}
During my research I also read about constructor injection:
#Component
public class MyComponent {
private final Cart cart;
#Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
}
What are the advantages and the disadvantages of both of these types of injections?
EDIT 1: As this question is marked as duplicate of this question i checked it. Cause there aren't any code examples neither in the question nor in the answers it's not clear to me if i'm correct with my guess which injection type i'm using.
Injection types
There are three options for how dependencies can be injected into a bean:
Through a constructor
Through setters or other methods
Through reflection, directly into fields
You are using option 3. That is what is happening when you use #Autowired directly on your field.
Injection guidelines
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Field injection drawbacks
The reasons why field injection is frowned upon are as follows:
You cannot create immutable objects, as you can with constructor injection
Your classes have tight coupling with your DI container and cannot be used outside of it
Your classes cannot be instantiated (for example in unit tests) without reflection. You need the DI container to instantiate them, which makes your tests more like integration tests
Your real dependencies are hidden from the outside and are not reflected in your interface (either constructors or methods)
It is really easy to have like ten dependencies. If you were using constructor injection, you would have a constructor with ten arguments, which would signal that something is fishy. But you can add injected fields using field injection indefinitely. Having too many dependencies is a red flag that the class usually does more than one thing, and that it may violate the Single Responsibility Principle.
Conclusion
Depending on your needs, you should primarily use constructor injection or some mix of constructor and setter injection. Field injection has many drawbacks and should be avoided. The only advantage of field injection is that it is more convenient to write, which does not outweigh all the cons.
Further reading
I wrote a blog article about why field injection is usually not recommended: Field Dependency Injection Considered Harmful.
This is one of the never-ending discussions in software development, but major influencers in the industry are getting more opinionated about the topic and started to suggest constructor injection as the better option.
Constructor injection
Pros:
Better testability. You do not need any mocking library or a Spring context in unit tests. You can create an object that you want to test with the new keyword. Such tests are always faster because they do not rely on the reflection mechanism. (This question was asked 30 minutes later. If the author had used constructor injection it would not have appeared).
Immutability. Once the dependencies are set they cannot be changed.
Safer code. After execution of a constructor your object is ready to use as you can validate anything that was passed as a parameter. The object can be either ready or not, there is no state in-between. With field injection you introduce an intermediate step when the object is fragile.
Cleaner expression of mandatory dependencies. Field injection is ambiguous in this matter.
Makes developers think about the design. dit wrote about a constructor with 8 parameters, which actually is the sign of a bad design and the God object anti-pattern. It does not matter whether a class has 8 dependencies in its constructor or in fields, it is always wrong. People are more reluctant to add more dependencies to a constructor than via fields. It works as a signal to your brain that you should stop for a while and think about your code structure.
Cons:
More code (but modern IDEs alleviate the pain).
Basically, the field injection is the opposite.
Matter of taste. It is your decision.
But I can explain, why I never use constructor injection.
I don't want to implement a constructor for all my #Service, #Repository and #Controller beans. I mean, there are about 40-50 beans or more. Every time if I add a new field I would have to extend the constructor. No. I don't want it and I don't have to.
What if your Bean (Service or Controller) requires a lot of other beans to be injected? A constructor with 4+ parameters is very ugly.
If I'm using CDI, constructor does not concern me.
EDIT #1:
Vojtech Ruzicka said:
class has too many dependencies and is probably violating single
responsibility principle and should be refactored
Yes. Theory and reality.
Here is en example: DashboardController mapped to single path *:8080/dashboard.
My DashboardController collects a lot of informations from other services to display them in a dashboard / system overview page. I need this single controller. So I have to secure only this one path (basic auth or user role filter).
EDIT #2:
Since everyone is focused on the 8 parameters in the constructor... This was a real-world example - an customers legacy code. I've changed that. The same argumentation applies to me for 4+ parameters.
It's all about code injection, not instance construction.
One more comment - Vojtech Ruzicka stated that Spring injects beans in such three ways (the answer with the biggest numbers of points) :
Through a constructor
Through setters or other methods
Through reflection, directly into fields
This answer is WRONG - because FOR EVERY KIND OF INJECTION SPRING USES REFLECTION!
Use IDE, set breakpoint on setter / constructor, and check.
This can be a matter of taste but it can also be a matter of a CASE.
#dieter provided an excellent case when field injection is better. If You're using field injection in integration tests that are setting up Spring context - the argument with testability of the class is also invalid - unless You want to write later on tests to Your integration tests ;)
Since dependency injection imply an inversion of control, I can't see an IOC in the following call:
Car car = (Car)ApplicationContext.getBean("car");
It's not Spring to work out itself the class, because I wrote Car myself into the code.
Moreover, all the books talk about two kind of DI: setter and constructor DI.
So I was wondering if the call ApplicationContext.getBean() imply any kind of dependency injection and IOC or there is no DI at all.
No. Getting your bean this way is not dependency injection. It is not getting injected. The fields of that bean are probably injected though.
Sometimes there's really no way around it, but in general, try to avoid this.
It's not Spring to work out itself the class, because I wrote Car myself into the code.
In that case you'd get a NoSuchBeanDefinitionException. You need to tell Spring about every class that it needs to manage -- there are multiple ways to do this, from autowiring to explicit definition in a descriptor.
The getBean does use the same configuration (applicationContext) than Spring's injection would use, but your example is not using any dependency injection. (Well the Car bean could be injected with it's dependencies so we don't really know from your example).
But normally dependency injection means you don't do any programmatic setting (Car car = something ) by yourself. The Spring container will create the car instance for you and either using the car's setters or it's constructor, will inject the dependencies the x needs to work.
I don't know why are trying to get the Car reference in this manner...If you want to use the reference of Car in another class, you can simply use setter or constructor injection as you said..If you use it as in the above manner, I can't see any kind of DI there.One thing we can surely say is that,the bean is managed by the IOC container as you are trying to get the reference from the application context...
I would like to make sure if I understand this correctly. Spring needs a setter to inject a field reference? Couldn't it do it by just detecting it as a public field?
Is there an alternative to this. From what I understand Java EE's #Inject annotation can do this without any problem. But I have always been inclined more to Spring.
This depends on how you're creating your bean. Spring does not require setters. There are a number of other ways:
Autowiring (with or without Qualifiers) via annotation at the field level
Constructor injection (either by xml or annotations in the code)
Public fields (as you suggested) might work, though i have never tried it, and would advise against it even if it does.
Unfortunately, the XML approach does not look into private fields (that i know of). You either need to add a setter, use the constructor, or set up some sort of autowiring.
Keep in mind, autowiring can be combined with XML. Spring will pay attention to your wiring annotations even if you create your bean via xml (as opposed to something like #Component and component scanning).
It is not necessary to have Setter to inject a reference, you can use Autowire on a public variable of a class or on the setter method, u can also inject beans using constructor-arg which is a good way of injecting dependencies and autowiring can be done on Constructors also. #inject also does the same functionality as #autowired, however #Autowired has an additional behaviour where it internally also uses #required attribute, to see if the bean has a references and injected properly.
Spring provides several alternatives for DI besides setter injection. For example, you can use constructor injection. Alternatively, you can use Spring's #Autowired annotation for constructor, field or setter injection. Since you mentioned it, I guess that you would also be interested in knowing that Spring supports the #Inject annotation.
Spring's DI works fine for singleton scope bean. However, regarding to prototype scope it is not convenient if the prototype bean itself will inject other beans. The thing is for prototype bean, I would like to create them using new keyword of Java with runtime constructor arguments which is hard to be statically described in XML bean configuration. Using new keyword makes the prototype bean out of Spring container, it is impossible to use Spring DI in them of course.
I am wondering how people solve problem like this? Of course I can use AspectJ to do myself injection as a compensation. But having two injection mechanisms is not an elegant solution to me.
You should be able to create prototype objects through context.getBean(name) or context.getBean(class) where context is ApplicationContext instance.
Another, perhaps even more convenient way is to use factory pattern with factory object being a singleton with all dependencies wired in and passing them to the constructed objects in factory.createInstance(...).
Mark you prototype bean with #Configurable
Spring allows for passing constructor values to the getBean() method, check out this SO-Post:
spring bean with dynamic constructor value
Furthermore, what would be wrong about retrieving a bean from the context, that is just partially initialized and you are setting the runtime-parameters yourself via setters?
Be aware, that Spring-Beans are by default Singletons, so in your Spring-Config you would have to explicitely specify them as being prototype-scoped!
I want to know how spring does dependency injection. I want the low level logic used.
Updates:
I want to know how the object references are injected to the constructors or setter methods, is it through Reflection or some byte code level.
Java components / classes should be as independent as possible of other Java classes. This increases the possibility to reuse these classes and to test them independently of other classes(Unit Testing). To decouple Java components from other Java components the dependency to a certain other class should get injected into them rather that the class itself creates / finds this object.
Class A has a dependency to class B if class A uses class B as a variable.
If dependency injection is used then the class B is given to class A via the constructor of the class A - this is then called construction injection; or via a setter - this is then called setter injection
The general concept of dependency injection is called Inversion of Control. A class should not configure itself but should be configured from outside.
A design based on independent classes / components increases the re-usability and possibility to test the software. For example if a class A expects a Dao (Data Access Object) for receiving the data from a database you can easily create another test object which mocks the database connection and inject this object into A to test A without having an actual database connection.
A software design based on dependency injection is possible with standard Java.
Spring just adds some simplifications in using dependency injection by providing a standard way of providing the configuration and by managing the reference to the created objects.
For more read this
Edit1:
When Spring initializes its context it creates all the beans defined eager in Spring application context.xml file.
Now suppose your Bean A has dependency of B then the Obj of B is already with Spring as it has been created successfully while Spring initialization. Then Spring will search for setter method in class A and will set B's Obj there.
Edit2:
Please read 5.4.1 Setter Injection
Configuration of dependencies are read from XML, annotations or Java DSL (JavaConfig). Then Spring DI engine wires the dependencies based on the metadata from the configuration using the Java reflection API.