I am interested in direct field dependency injection. Traditionally, Spring supports both constructor injection (supplying arguments to constructors) and setter-based injection (calling setters on a call).
However, Spring is also capable of direct field injection (setting member fields of an object without a setter method), as evidenced by annotating fields with @Autowired
. Autowiring is limited to just "beans", so primitive values cannot be injected (although this can somewhat be circumvented by creating beans of class "java.lang.String" - this works, but has the normal caveats of autowiring.) In addition to this, Spring supports @Value
to directly set values to member fields from properties etc.
Yet, Spring does not allow properties to be directly set to member fields (without autowiring).
My question is: why?
It is obviously capable of doing so, so why doesn't it? Are there any big negative side-effects that prevent this? Or is the capability somehow limited so that only autowiring makes sense? Does it need some bigger hacks than calling setters?
Note that I do not wish to discuss the relative merits of having setters and getters in general, just the reasons why Spring has made this choice.
The @Autowired annotation uses reflection to make private fields accessible (see this related question). I can see three things why it isn't used in Spring configuration files.
I think I found the answer myself. I went over to the Spring source code and saw how the features were actually implemented. This is what I found:
Setting properties via XML is probably the oldest part of Spring, and it relies very heavily on "java.beans" classes for introspection, property enumeration, etc. And quite obviously, those do not support field introspection at all. On top of this is the type conversion machinery which determines how the property value can be converted to a suitable value for the property in question. There are no neatly separable pieces here.
All the @Autowired etc. stuff is implemented in a BeanPostProcessor, which has it's own type matching mechanic, which has nothing to do with the type conversion. That is also why it only injects beans. Same thing pretty much for @Value, it is just something that is resolved on the spot there and has nothing to do with properties.
So, adding field injection support, for properties in particular, is not a trivial engineering effort as the parts of the code that do one or the other are pretty much completely separate.
This doesn't exactly answer "Why?", but I think this is a more compelling explanation as to why Spring hasn't added direct field dependency injection than the other explanations I've heard. Unless they have something fundamental against it (which I doubt, considering that they want to allow configuration of existing third party classes, not just JavaBeans), then it's just a matter of engineering effort to get the functionality in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With