Dependency injection on a protected field using #Inject [duplicate] - java

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 ;)

Related

#Autowired during testing

I have a question.
#Autowired annotation is not recomended since Spring Boot 2.x. Then I have to use constructor.
but in during testing (JUnit 5) i don't have any warning
Questions:
that means using #Autowired during testing is good practicle ?
JUnit and Spock(which is actually based on JUnit) frameworks are enforcing tests classes to have no-args constructors only. So it's not even achievable - probably that's why you weren't prompted about potential issue.
Test classes must not be abstract and must have a single constructor.
from junit documentation
To add a bit more to this article
Additional pros for constructor autowiring:
you can validate what kind of bean is being injected, either by code or by debugging tools if something suddenly stops working as expected.
it's easier to create class instance for testing purposes, especially if it has private/protected attributes that should be mocked and you are writing tests in pure java.
field injection is not recommended for a several of concepts, most of them connected to the usage of the class in other places, e.g the class can be instantiate with the default (no-args) constructor, thus will not be created with all or any dependencies
because the actual class can be instantiate in other places like at the testing part of code you get this warning
because the testing class usually isn't meant to be instantiate at any other parts of the code, you get no warning, this doesn't mean it's ok, it's still field injection and is still not recommended
you can read more about this here

Injection of Multiple Conflicting Dependencies in Spring

I have a Spring bean class which requests dependencies to be injected. However, in my class, I am manually wiring different dependencies to the same private class variable. What happens in this scenario? Which injection takes precedent?
Details:
I have created a Spring bean class called BadmintonCoach.
It relies on an IfortuneService helper. IfortuneService is an interface with TWO different implementations. The two implementations are:
FortuneService_RESTful
FortuneService_Random
In my badmintonCoach class, I have created a private variable to receive the injection from Spring:
private IFortuneService theFortuneService
That is to say, I am manually wiring up the the injected dependency to this private member, theFortuneService
I am injecting these iFortuneService dependencies using method injection.
BUT here is the problem: I have TWO methods, both of which request an injection from Spring of the type iFortuneService. One method requests one implementation (FortuneService_RESTful) and the other method requests a bean of the other implementation (FortuneService_Random).
Both of these methods set this.theFortuneService equal to its respective requested helper. So what I have within my BadmintonCoach class is:
private IFortuneService theFortuneService
#Autowired
#Qualifier("fortuneService_Random")
public void randomMethod_ONE(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_ONE!");
this.theFortuneService = theFortuneService;
}
#Autowired
#Qualifier("fortuneService_RESTful")
public void randomMethod_TWO(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_TWO!");
this.theFortuneService = theFortuneService;
}
My question then, is:
Which of the two wirings wins out? Why? How does Spring decide the ORDER of its injections? What determines the order of the injections? Is it random? Is it injected in alphabetic order of the method names? Is there an order of injection between constructor, setter, field and method injections?
What am I seeing when I run my program? I am seeing the injection of fortuneService_RESTful win out, but it is unclear to me whether this is by chance or by design from within Spring's logic.
Here is another thought:
What if, instead of requesting different implementations of the IFortuneService interface, the two methods above asked for the same bean but that bean was prototyped? Clearly, there would be a new incarnation created for each request and there would only be one helper class assigned to my BadmintonCoach class. But which incarnation would win out?
I can provide the whole of my code if it will make my question clearer.
If you are wondering WHY I have written conflicting code? It is plain and simple curiosity to try and understand how Spring works behind the scenes.
OK folks, it has taken a day for me to see this but I can confirm that what happens here is indeed random!
Yesterday, I was exclusively seeing method_ONE win out. Today, I am seeing method_TWO win out. I can therefore conclude that the order of injections by Spring is indeed random!
Thomas Klager had provided a suggestion in the comments above which may explain this phenomenon:
One obvious reason [for this] is that using annotation based injections, spring
needs to list the methods of a class using Class.getDeclaredMethods()
or Class.getMethods(). Neither of these methods return the methods in
any particular order.
I still find it a mystery how execution of the same logic by Spring (ie: Class.getDeclaredMethods() or Class.getMethods()) can yield random results like this.
It is very important to be aware of this limitation! When writing code, you may find yourself wanting to use the services of injected dependencies which in turn depend on the services other injected dependencies. It is clear from this experiment that this could potentially be dangerous and therefore you should not layer your wiring in this manner. That is to say, your wiring should always be single tiered if it spans multiple methods, otherwise, you risk spurious output from your program. An illustration of this danger can be seen in Slim's answer in this link.

Spring's AutowiredAnnotationBeanPostProcessor and constructor injection

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.

Finding stateful singleton beans

Today, we found this pattern in our code:
class Foo {
private List<String> errors;
public void addError(String error) { ... }
public List<String> getErrors();
}
While the code seems to work, this is a singleton Spring bean and it's injected in several independent places and the consumers of the bean assume that they each have their own list of errors. So this introduces subtle bugs.
The obvious solution is to educate developers to avoid this kind of error but I was wondering if there is a static or runtime code analysis tool which can find this kind of bug.
For example, a bean postprocessor could analyze the bean before it's returned and look for private fields that aren't #Autowired.
After pouring some more brains (ours and other peoples) on this, we came up with this approach:
Install a BeanPostProcessor which makes sure that all singleton beans (i.e. where the scope in the bean definition is Singleton) have the custom annotation #Stateless on the actual bean type.
We chose a custom annotation instead of reusing #Singleton since we need this functionality elsewhere, too.
If the annotation is missing, the factory throws an error.
In a unit test, we use ClassPathScanningCandidateComponentProvider with out custom annotation to locate all classes on the classpath. We can then do the complex and expensive tests to make sure the bean has no state that changes after the initial configuration (i.e. after the autowiring has happened).
The second step could become a little bit easier if we moved the autowired fields into the constructor but we don't like methods that take many, many arguments. It would be nice if Java or an IDE could generate builders from the bean code. Since that's not the case, we stick to autowired fields and/or setters.
You could create a JUnit test that would load your app config.
This could combine ListableBeanFactory from here :
Can I dynamically create a List by scanning the beans in a spring configuration file?
with the 'isSingleton' check here :
How to enforce a prototype scope of Spring beans
i.e. list all the beans in the app context, then check to see which are singletons.
This would let you find all singleton beans...although it wouldn't really prevent your error case where someone treats one of these singletons as if it were not.

Getting around setter injection using mockito's #InjectMocks

I have an abstract class with two Map fields. One I would like to mock and inject into an object of a subclass of AbstractClass for unit testing. The other I really don't care much about, but it has a setter.
public abstract class AbstractClass {
private Map<String, Object> mapToMock;
private Map<String, Object> dontMockMe;
private void setDontMockMe(Map<String, Object> map) {
dontMockMe = map;
}
}
When using #InjectMocks, it automatically tries to inject in the order: constructor, setter, field. It checks if it can inject in each of these places by checking types, then names if there are multiple type possibilities. This doesn't work well for me, because my mocked mapToMock is actually injected into dontMockMe via its setter. I cannot edit this abstract class. Is there any way for me to get around the setter injection? Thank you in advance!
Well this is a corner case, where automatic injection won't work in the way Mockito injection is currently designed. Also Mockito suffer from some shortcomings when there is multiple fields with the same types.
So to understand why this doesn't work let's dive a bit in the way Mockito performs injection :
It will try to inject dependencies via constructor injection, if it successes it won't try the following steps in order to protect the newly created instance from eventual side effects.
Then if constructor injection did not happen (no arg constructor, or object already instantiated), then Mockito will look for matches between mocks and setters. But it has to make some choices for it to happen automatically.
If there is only mock of type A and only one setter with type A then setter injection will happen.
If there is either multiple mocks or setters of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
Then if there is still some mocks left for injection, field injection might happen, using the same algorithm as with setter :
If there is only mock of type A and only one field with type A then field injection will happen.
If there is either multiple mocks or field of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
At the moment your code is stuck at stage 2.1 because there is probably only one mock available.
That being said with the current implementation of Mockito there is no real elegant solution, it is necessary to write yourself the injection code. And that is actually the wanted point with Mockito injection, if injection is too complex or weird, then you will have to write it out ; writing this boilerplate code is actually the best tool to question the current design.
Mockito injection is really designed for simple, straight designs.
In my opinion, I find wrong :
to mock a Map, a type you don't own, that might cause many problems.
to mock only a single map in tested object, that means your test knows too much about the inner working of the tested object.
It would benefit the design if you refactor the code and make the collaborators emerge. With clear dependencies/collaborators it will most certainly make the injection clearer too. Also the test should focus on asserting the interactions with the collaborators not how data how the implementation is done, data should only be tested as a result to a given input.

Categories