Sometimes you need an instance of class A, but you do not store A in the fields of the class that uses A.
You just need A instance to perform a one-shot operation. Or, you use A instance to obtain an instance of B, and you are storing B in the field.
In those cases, a setter (or constructor) autowire will suit you better.
You will not have unused class-level fields.
Concrete example:
You need to construct RabbitTemplate (an object that sends messages to RabbitMQ)
To construct it, you need ConnectionFactory
http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-
You do not need to store that ConnectionFactory. In that case, code that looks like this:
Class MyClass {
private RabbitTemplate template;
@Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...will serve you better than directly autowiring the ConnectionFactory field.
In this example, autowiring at the constructor level would be even better, because your object will always be completely constructed. It will be clear that ConnectionFactory is a mandatory dependency, not an optional one.
Answer from Bartosz Bilicki on Stack OverflowSometimes you need an instance of class A, but you do not store A in the fields of the class that uses A.
You just need A instance to perform a one-shot operation. Or, you use A instance to obtain an instance of B, and you are storing B in the field.
In those cases, a setter (or constructor) autowire will suit you better.
You will not have unused class-level fields.
Concrete example:
You need to construct RabbitTemplate (an object that sends messages to RabbitMQ)
To construct it, you need ConnectionFactory
http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-
You do not need to store that ConnectionFactory. In that case, code that looks like this:
Class MyClass {
private RabbitTemplate template;
@Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...will serve you better than directly autowiring the ConnectionFactory field.
In this example, autowiring at the constructor level would be even better, because your object will always be completely constructed. It will be clear that ConnectionFactory is a mandatory dependency, not an optional one.
With @Autowired annotation, you don't need a setter method. Once your bean's constructor is done with allocating/creating the object, Spring will scan for this annotation and would inject the object instances that you annotated.
While if you have setter and if you are still using xml config, you would explicitly set properties.
Having said that, You could annotate your constructor and setter method with autowired annotation which i would prefer as this would give me flexibility later on to move away from Spring (although i wont do it).
Videos
@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.
@Autowired is not the same as @Required.
The @Required-Annotation is specialized for telling Spring that this property has to be injected by the information given in the XML-configuration-file (eager) and not through annotations. And that doesn't matter when you use the @Autowire-Annotation.
The @Autowire-Annotation (as in your code-example), tells the ApplicationContext (a.k.a the Spring-IoC-Containter) to inject the desired dependency. (No matter how, if its by using annotations or the XML-File of the ApplicationContext).
The @Required-Annotation, tells the ApplicationContext that this property has to be mentioned in the XML-file (The XML-File of the ApplicationContext), but the Annotation on its own doesn't tell to inject the dependency. So it is used to check if it is in the XML-configuration file, but not to inject a dependency. The injection is done because the property is mentioned in the XML-file.
So in the end it tells that the injection has to be done because of a configuration in the XML-File. But again: The annotation doesn't tell that the dependency has to be injected, but that it has to be mentioned in the XML-File - which then lets the dependency be injected.
With mentioning the property in a XML-File I mean such a configuration for instance:
<bean id="MyClass" class="com.myclasses.common.MyClass">
<property name="someProperty" value="ValueThatHasToBeInjected" />
</bean>
So why should I use it over the @Autowired-Annotation?
You should use it when the dependency has to be injected due to the informatoin given in the XML-configuration file.
Can you give me an example?
Well, there is already a very good example on this website. where this is also explained.
1) You can think of @Required as a check that the property has been eagerly initialised. In other words it requires that it's been injected via configuration (xml or annotation). If annotation is used then you'll see it alongside @Autowired. If the Bean injected does not exist the application fails to startup with a runtime exception.
2) Nothing more nothing less. @Required is very specific in what it's meant to be: a) only applicable on methods, b) requires the bean or else application runtime error on startup. Again, you need dependency injection either via annotation or xml.
3) Most likely you want to know at startup if a Bean is failed to be injected and for that reason you can have @Required along with @Autowired for expressiveness. Functionality-wise you don't need it if you have @Autowired.
Extra notes:
@Autowired has more functionality on the other side of the coin that is - when you want to achieve laziness. So on a setter method:
- as you mentioned
@Autowired(required = false) - Can also be paired with
@Lazy - you can have
@Autowired(without required = false) on a setter method whose param is Java 8's Optional achieving the same effect.
Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
- the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
- the dependencies can be final, which helps with robustness and thread-safety
- you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.
I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()), which is NOT good as you need SomeOtherService object (as a dependency) for your SomeService.
Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Option(B) is preferred approach as it does NOT allow to create SomeService object without actually resolving the SomeOtherService dependency.