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.
Related
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.
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
I couldn't find any reasonable answer here on SO so I hope it's not a duplicate. So why should I prefer setter or constructor injection over simple
#Inject
MyBean bean;
I get the usage of the constructor injection if you need to do something with injected bean during your class initialization like
public void MyBean(#Inject OtherBean bean) {
doSomeInit(bean);
//I don't need to use #PostConstruct now
}
but still, it's almost the same like #PostConstruct method and I don't get setter injection at all, isn't it just a relic after Spring and other DI frameworks?
Constructor and property injection gives you the option to initialize the object even in a non CDI environment easily, e.g a unit test.
In a non-CDI environment you can still simply use the object by just passing the constructor arg.
OtherBean b = ....;
new MyBean(b);
If you just use field injection you usually must use reflection to access the field, because fields are usually private.
If you use property injection you can also write code in the setter. E.g. validation code or you clear internal caches that hold values which are derived from the property that the setter modifies. What you want to do depends on your implementation needs.
Setter vs constructor injection
In object-oriented programming an object must be in a valid state after construction and every method invocation changes the state to another valid state.
For setter injection this means that you might require a more complex state handling, because an object should be in a valid state after construction, even if the setter has not been invoked yet. Thus the object must be in a valid state even if the property is not set. E.g. by using a default value or a null object.
If you have a dependency between the object's existence and the property, the property should either be a constructor argument. This will also make the code more clean, because if you use a constructor parameter you document that the dependency is necessary.
So instead of writing a class like this
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public Customer findById(String id){
checkDataSource();
Connection con = dataSource.getConnection();
...
return customer;
}
private void checkDataSource(){
if(this.dataSource == null){
throw new IllegalStateException("dataSource is not set");
}
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
}
you should either use constructor injection
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public CustomerDaoImpl(DataSource dataSource){
if(dataSource == null){
throw new IllegalArgumentException("Parameter dataSource must not be null");
}
this.dataSource = dataSource;
}
public Customer findById(String id) {
Customer customer = null;
// We can be sure that the dataSource is not null
Connection con = dataSource.getConnection();
...
return customer;
}
}
My conclusion
Use properties for every optional dependency.
Use constructor args for every mandatory dependency.
PS: My blog The difference between pojos and java beans explains my conclusion in more detail.
EDIT
Spring also suggests to use constructor injection as I found in the spring documentation, section Setter-based Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Constructor injection is also a better way when you think about unit tests, because it is easier to call the constructor instead of setting private (#Autowired) fields.
When using CDI, there is no reason whatsoever to use constructor or setter injection. As noted in the question, you add a #PostConstruct method for what would otherwise be done in a constructor.
Others may say that you need to use Reflection to inject fields in unit tests, but that is not the case; mocking libraries and other testing tools do that for you.
Finally, constructor injection allows fields to be final, but this isn't really a disadvantage of #Inject-annotated fields (which can't be final). The presence of the annotation, combined with the absence of any code explicitly setting the field, should make it clear it is to be set by the container (or testing tool) only. In practice, no one will be re-assigning an injected field.
Constructor and setter injection made sense in the past, when developers usually had to manually instantiate and inject dependencies into a tested object. Nowadays, technology has evolved and field injection is a much better option.
Accepted answer is great, however it doesn't give credit to the main advantage of constructor injection - class immutability, which helps to achieve thread-safety, state safety, and better readability on the classes.
Consider you have class with dependencies and all of those dependencies are provided as constructor arguments, then you can know that the object will never exist in a state where dependencies are invalid. There is no need for setters for those dependencies (as long as they are private), so the object is instantiated to a full state or is not instantiated at all.
An immutable object is much more likely to well behave in an multithreaded application. Although the class still needs to be made internally thread-safe, you don't have to worry about external clients coordinating access to the object.
Of course this can be usefull only in certain scenarios. Setter injection is great for partial depencdency, where for example we have 3 properties in a class and 3 arg constructor and setters methods. In such case, if you want to pass information for only one property, it is possible by setter method only. Very useful for testing purposes.
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
Using Spring annotations to autowire dependencies, I'm getting a org.springframework.beans.factory.NoUniqueBeanDefinitionException because I have a class with a private constructor and a public static get-method, both of which return instances of the class.
That class is annotated with the #Service annotation, and the static get method is annotated with #Bean.
I know that I can use the #Qualifier annotation at the injection point to disambiguate, and if I just remove the #Bean annotation, Spring uses the constructor without issue.
But I'd prefer Spring to use the static method -- maybe the method does some setup (Yes, I know that Spring beans are by default singleton -- still, maybe I have a reason to want to force all construction to go through my method, rather than directly to my constructor.)
Is there a way to tell Spring, as a general policy, to prefer public methods to non-public ones (in this case, the private constructor) when satisfying dependencies?
Or, less appealingly,
Is there a way (some annotation) to explicitly exclude the constructor in the #Service class from Spring's consideration?