Difference between Dependency Injection and #DependsOn - java

we are using Spring in our project and today I found, in my eyes, a strange beaviour. In my opinion Dependency Injection and the annotation #DependsOn should be the same in the following both cases
#Bean
public ClassA classA(){
//code
}
#Bean
public ClassB classB(ClassA classA){
someMethodWhichNeedsClassA()
}
and
#Bean
public ClassA classA(){
//code
}
#Bean
#DependsOn("classA")
public ClassB classB(){
someMethodWhichNeedsClassA()
}
It seems, that those both ways are not identical. I am not allowed to share my code, but in the first case I have access to a list which is filled in the first Bean, but not in the second case.
I tried to find something in the documentation or in other blogs but without success.
Has anybody an idea if there is any differences between those both ways, because I thougth it has something to do with ordering of bean creation and thats all.
Thanks for any help

Spring, by default, manages beans' lifecycle and arranges their initialization order. This is the case in your first example. While in your second example you tell Spring that bean B depends on A. So spring will create bean A before bean B.
#DependsOn from spring docs:
Beans on which the current bean depends. Any beans specified are
guaranteed to be created by the container before this bean. Used
infrequently in cases where a bean does not explicitly depend on
another through properties or constructor arguments, but rather
depends on the side effects of another bean's initialization.
Baeldung spring DependsOn

In simple words there are two scenarios
If beans creation is in sequence, spring will start initializing from top to bottom. In this case, depending on bean needs to listed first
If beans creation is not in sequence and getting managed through multiple appconfig, in this we can use #DependsOn annotation to make sure that dependent beans are initialized before getting used.

If bean B calls any method on bean A (or passes to some other objects/methods that eventually call methods of bean A), then dependency injection is sufficient.
Bug there are cases when bean B does not need to call any methods on bean A,
but dependsn on the result of initialization of bean A. Suppose bean A during its initialization creates tables in database,
and bean B needs these table before it can be use. Then dependency injection makes no sense. Any code quality check will show you that
injected variable is not used and thus is not needed.
In such case you don't inject bean A into B, but declare dependency on bean A.
Briefly: If bean B calls bean A, use dependency injection. If bean B only needs results of initialization of bean A, use #DependsOn.

Related

Spring setter injection not mandatory

I read that There is no guarantee in a setter injection that the dependency will be injected as opposed to constructor injection that the dependency is mandatory.
I really don't understand that point. If I write the following method:
#Autowired
public void setMyBean(MyBean otherBean){
this.otherBean = otherBean;
}
what does it mean that otherBean won't be injected?
DI exists in two major variants: Constructor-based dependency injection and Setter-based dependency injection.
Constructor-based Dependency Injection
Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency.
Setter-based Dependency Injection
Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean.
Again, constructor injection ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state (not having passed its collaborators). In other words, when using constructor injection you do not have to use a dedicated mechanism to ensure required properties are set (other than normal Java mechanisms).
But in setter based injection if the dependencies is not found the object is created, but the dependent object will be null. Means, setter injection does not ensures dependency Injection. You can find a detailed article here.
Note that use of the #Required annotation on a setter method can be used to make the property be a required dependency.
if you are using setter based injection in your bean then your bean will initialise no matter all dependencies have been resolved or not, but you will get NPE when try to use these non resolved/initialised dependencies in your code.
But in Constructor based injection your bean will initialise once all dependencies have been resolved.
Whenever we use #Autowired, Spring makes sure the relevant bean exists and gets injected for use.
If this cannot be done, Spring throws an exception and the application fails to start.
The statement actually is in reference to testing your code. By this I mean, If using setter based dependency injection it may be possible that one will forget to inject the required bean and the corresponding test cases might fail.
constructor based dependency injection ensures that one has to init all required beans before actually using the required code.
You can read it in detail over here

#Inject Instance with custom quailfier annotation on class type

Lets say we have
class TestClass1 {
#Inject #Any #BBB(PARAM1)
Instance< Product > instaces;
#Produces #BBB(PARAM1)
Product first(){...}
#Produces #BBB(PARAM1)
Product second(){...}
}
and
class TestClass2 {
#Inject #Any #BBB(PARAM2)
Instance< Product > instaces;
#Produces #BBB(PARAM2)
Product first(){...}
#Produces #BBB(PARAM2)
Product second(){...}
}
When i put #BBBs on class and remove from methods instances are empty. Is how it works and I have to replicate #BBB on every #Produces methods OR something I have missed?
#BBB is annotated with #Qualifier and RUNTIME retention
Not sure I fully understand your question, but I hope this will clarify it. I think you are mixing several things together.
1) Producers
Those are methods/fields which are effectively considered beans! This means that on top of producer you have to define what kind of bean will it create. That boils down to qualifiers, scope, stereotypes,... Whatever you need/want there. This also allows you to have multiple producers which will only differ in, say, qualifier with which they create the bean. So yes, you need to repeat it on each producer, for it may make a great difference.
2) Your classes
Your are themselves beans (dependent scope in this case) and you can specify all the CDI stuff on them - scope, qualifiers, etc. This will not propagate to the producers inside the beans. If you think about it, that would mean that should your class be application scoped, anything it produces would also be application scoped, which is not the case.
Your source of confusion might also be interceptor/decorator (or rather their binding) which can be placed either on bean method (enabling interception for given method) or on top of whole class (enabling interception for all methods).

List injection order in Spring IoC container

Suppose I'm injecting list of some beans:
#Autowired
List<SomeBean> beans;
What is default injection order in this situation?
I know about Ordered interface and #Order annotation, I'm asking only about default behavior.
What I've noticed is that in case of manual bean registration:
context.register(SomeBeanA.class);
context.register(SomeBeanB.class);
context.register(SomeBeanC.class);
This beans is injected in the exact same order as I registered them: 1 element in list is SomeBeanA, 2 — SomeBeanB, 3 — SomeBeanC.
Is there is any guarantee of this behavior? I mean can I be sure that it won't change in further release?
Thanks.
If you want to guarantee the order of the autowired list I would use the order interface or annotation.
In fact the list is ordered anyway and each bean not declaring an explicit order resolves to a default order. (Which is min integer by default if I'm not mistaken)
Take a look at this class:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationAwareOrderComparator.html

How is #Autowired implemented in Spring

I would really like to have even a basic understanding of how is #autowired
implemented in Spring.
Reflection should be somehow implied in its implementation, but I cannot figure out how.
Can you help ?
Autowiring through #Autowired is performed by a BeanPostProcessor implementation, specifically org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.
This BeanPostProcessor processes every bean, will scan its class (and superclasses) for any #Autowired annotations, and, depending on what is annotation (a constructor, field, or method), it will take appropriate action.
For constructors
Only one constructor (at max) of any given bean class may carry this
annotation with the 'required' parameter set to true, indicating the
constructor to autowire when used as a Spring bean. If multiple
non-required constructors carry the annotation, they will be
considered as candidates for autowiring. The constructor with the
greatest number of dependencies that can be satisfied by matching
beans in the Spring container will be chosen. If none of the
candidates can be satisfied, then a default constructor (if present)
will be used. An annotated constructor does not have to be public.
For fields
Fields are injected right after construction of a bean, before any
config methods are invoked. Such a config field does not have to be
public.
For methods
Config methods may have an arbitrary name and any number of arguments;
each of those arguments will be autowired with a matching bean in the
Spring container. Bean property setter methods are effectively just a
special case of such a general config method. Config methods do not
have to be public.
All of this is done through reflection.
Further reading:
How do I invoke a Java method when given the method name as a string?
Is it possible in Java to access private fields via reflection

Spring #Autowired for setter methods vs non-setter methods

According to #Autowired javadoc:
Marks a constructor, field, setter method or config method as to be autowired
by Spring's dependency injection facilities. Only one constructor (at
max) of any given bean class may carry this annotation, indicating the
constructor to autowire when used as a Spring bean. Such a constructor
does not have to be public. Fields are injected right after
construction of a bean, before any config methods are invoked. Such a
config field does not have to be public. Config methods may have an
arbitrary name and any number of arguments; each of those arguments
will be autowired with a matching bean in the Spring container.
Bean property setter methods are effectively just a special case of such a
general config method. Such config methods do not have to be public.
In the case of multiple argument methods, the 'required' parameter is
applicable for all arguments. In case of a Collection or Map
dependency type, the container will autowire all beans matching the
declared value type. In case of a Map, the keys must be declared as
type String and will be resolved to the corresponding bean names. Note
that actual injection is performed through a BeanPostProcessor which
in turn means that you cannot use #Autowired to inject references into
BeanPostProcessor or BeanFactoryPostProcessor types. Please consult
the javadoc for the AutowiredAnnotationBeanPostProcessor class (which,
by default, checks for the presence of this annotation).
My questions are:
What is meant by config methods?
And also, let's say I have a setter method with #Autowired and some arbitrary methods with #Autowired. I assume that setter method is invoked by spring automatically after the bean instantiation, while random-named #Autowired methods won't be invoked, am I right?
Also how does spring understand which #Autowired method should be invoked after the instantiation (setters), while others shouldn't? And how does this correlate with a statement from javadoc, saying that:
Bean property setter methods are effectively just a special case of
such a general config method
One final question: where I can read about it? since spring documentation doesn't have any information on that and I wasn't able to find the exact logic used by spring in its javadoc.
#Autowired annotation can be used with constructor, setter method or just any other method.
Whenever Spring finds #Autowired annotation it will try to find beans matching to method parameters and will invoke that method. If multiple methods (setter or non-setter) have #Autowired annotation, all will be invoked by Spring after bean instantiation.
A config method is a factory-like method, which in this case would get the paramaters autowired:
#Autowired
public SomeObject initSomeObject(Object1 o1, Object2 o2, ...) {
#Autowired merely ensures that Spring will (attempt to) provide the needed parameters.
Config-method in this context refers to methods that you would specify under init-method or #PostConstruct
Setter as you already know is like setXXX
So obviously there is no difficulty in finding which is which.
At the same time note that spring can not autowire based on parameter names.

Categories

Resources