3
votes

So my question why did @javax.annotation.Resource worked but @AutoWired did not. For a test on a Restful controller, I was trying to inject MappingJackson2HttpMessageConverter with @Autowired, on start up the container failed to find a qualifying bean even though that class was on the path. Now, to solve this I went into a context xml file and added the bean:

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>

Then in the test class had member variable:

@javax.annotation.Resource(name="jsonConverter")
private  MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

Then spring finds the bean. Does Autowire only work for beans that were identified as beans by package scan?

Thanks ahead of time.

3

3 Answers

3
votes

Autowired and Resource merely make the class types of annotated field, method or constructor eligible for dependency injection - it does not automatically add those types to the context of your Spring application!

So, as you suspect, in order for the annotations to work, you have to ensure that the auto-wired types are available in the application context yourself, e.g. with the Component annotation and package scan or by explicitly defining the bean in your application-context.xml as you did in your example.

3
votes

In both cases Spring wires the dependency only when the bean getting wired is defined into spring context. You have to either define the bean in xml file or use annotation based bean definition to make it eligible for wiring.

On the other note, @Resource does name based wiring whereas @Autowire by default goes with type based.

Please see @Resource vs @Autowired for more context on topic.

2
votes

This is from Spring reference. The second para may provide pointers.

If you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if is technically capable of referring to a bean name through @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.

As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through @Autowired, because type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection or map bean by unique name.

@Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, @Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.

I think, in your case, there could be some issue with the default autowiring by name. So I guess Spring would be able to @Autowire the bean if you mention the qualifier. But then again if it is a case for @Resource, I think I'd prefer using it.