×
Community Blog Spring Exploration: If There Is @Resource, Why Do We Need @Autowired?

Spring Exploration: If There Is @Resource, Why Do We Need @Autowired?

This article defines @Resource and @Autowired and explains why both work with Spring.

By Junwu Wang (Chuxuan)

When it comes to Spring dependency injection, the first thing that comes to mind is @Resource and @Autowired. Many articles only explain the functional differences but do not mention why Spring supports two similar annotations. I wonder if readers have ever thought about why @Autowired is still needed even though @Resource supports both name and type.

After reading this article, you will learn:

  1. Where are @Resource and @Autowired from?
  2. Why does Spring support these two similar annotations?
  3. Why does Idea show a yellow warning when the @Autowired attribute is injected?
  4. How to use @Resource and @Autowired

Where Are @Resource and @Autowired From?

If you want to figure out the answer, you must understand what they are.

@Resource was released with JSR 250 on May 11, 2006. The official explanation for @Resource is listed below:

The Resource annotation marks a resource that is needed by the application. This annotation may be applied to an application component class, or to fields, or methods of the component class. When the annotation is applied to a field or method, the container will inject an instance of the requested resource into the application component when the component is initialized. If the annotation is applied to the component class, the annotation declares a resource that the application will look up at runtime.

You can see that it resembles a definition and is freely implemented by other components or frameworks.

@Autowired was released with Spring 2.5 on November 19, 2007, and @Resource was officially supported. The official explanation for @Autowired is listed below:

Mark a constructor, field, setter method, or configuration method to be autowired by Spring's dependency injection tools.

As you can see, @Autowired is Spring's son, and @Resource is an implementation of Spring's definition of it. Therefore, @Autowired and @Resource are similar in features. Why does Spring support @Resource and @Autowired?

I specifically checked the official documents of Spring 2.5. There is a paragraph in the document that says:

However, Spring 2.5 dramatically changes the landscape. As described above, the autowiring choices have now been extended with support for the JSR-250 @Resource annotation to enable autowiring of named resources on a per-method or per-field basis. However, the @Resource annotation alone does have some limitations. Spring 2.5, therefore, introduces an @Autowired annotation to further increase the level of control.

The general meaning is that Spring 2.5 supports annotation autowiring. It already supports the JSR-250 @Resource annotation to enable autowiring of named resources on a per-method or per-field basis. However, @Resource cannot cover all scenarios unless @Autowired with greater granularity is applied.

So, granularity is the key. What does granularity mean?

Why Does Spring Support Both @Resource and @Autowired?

Let's start with the functions of the two annotations to figure out what granularity is.

@Autowired

  • Type injection

@Resource

  • Inject name first. Look for the type if the name cannot be found.

As for the granularity of functions, @Resource already contains @Autowired, and the former's granularity is even larger. Was it not the case in Spring2.5? I went to the Spring 2.5 document again, which clearly stated:

When using @Resource without an explicitly provided name, if no Spring-managed object is found for the default name, the injection mechanism will fall back to a type-match.

Wasn't this the same as now? I was in a mess then. What does granularity mean? After searching many forums, a passage from stackoverflow caught my attention:

Both @Autowired and @Resource work equally well. But there is a conceptual difference or a difference in the meaning.

  • @Resource means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.
  • @Inject or @Autowired try to wire in a suitable other component by type.
    So, basically these are two quite distinct concepts. Unfortunately, the Spring-Implementation of @Resource has a built-in fallback, which kicks in when resolution by-name fails. In this case, it falls back to the @Autowired-kind resolution by-type. While this fallback is convenient, IMHO, it causes a lot of confusion because people are.

Let’s summarize the messages above. Although @Autowired and @Resource are similar in functionality, they differ in concept and meaning.

  • @Resource gives a definite known resource by name.
  • @ Autowired tries to connect other appropriate components by type.

But @Resource starts when the resolution by name fails. In this case, it will resolve by type, causing conceptual confusion because developers are not aware of the conceptual difference but tend to use @Resource autowiring based on type.

It turns out that Spring's granularity refers to resource range. @Resource is looking for definite and known resources, which is equivalent to giving a coordinate for searching. @Autowired tries to search for suitable resources in an area.

The answer to the question above is clear.

Why does Spring support the two functionally similar annotations?

  • They are conceptually different. @Resource prefers to find known resources, while @Autowired searches for resources by type.
  • Facilitate the migration of other frameworks. @Resource is a specification that can be compatible with Spring as long as it conforms to other JSR-250 frameworks.

Since @Resource is more inclined to find known resources, why does it also have the function of injecting by type?

  • Personal Guess: It needs to be compatible with other frameworks switched from Spring. This way, even if developers only use Resource, they still maintain Spring's powerful dependency injection function.

Differential Treatment of Spring

Now, I believe everyone knows whether to use @Resource or @Autowired. There is a small detail in the daily code writing. I don't know if you have noticed that Idea will show a yellow warning when using @Autowired on the attribute and recommend using the constructor injection. However, when we use @Resource, it won't happen. Why? The warning is shown below:

1

Why Does Idea Show a Yellow Warning When @Autowired Is on Attribute and Recommend Using the Constructor Injection?

The Spring document has already given the answer, mainly including these points:

1. @Autowired Cannot Declare the Attribute of a Constant

Attribute-based dependency injection does not apply to a field declared as final because the field must be deinstantiated when the class is instantiated. The only way to declare immutable dependencies is to use constructor-based dependency injection.

2. It Is Easy for @Autowired to Ignore the Single Principle of the Class

A class should only be responsible for a single part of the software application's functionality, and all of its services should be tightly tied to that responsibility. If you use the field injection, it's easy to have a lot of dependencies in your class, and everything looks fine. However, if you switch to constructor-based dependency injection, as more dependencies are added to your class, the constructor will become larger, and the code will start to smell, sending a clear signal that there is a problem. Constructors with more than ten parameters clearly indicate that the class has too many dependencies, so you have to pay attention to the single problem of the class. Thus, while attribute injection does not directly break the single principle, it can help you ignore the single principle.

3. Circular Dependency Problem

Class A requires an instance of Class B through constructor injection, and Class B requires an instance of Class A through constructor injection. If you configure beans for classes A and B to inject into each other, you can quickly find out the situation with the constructor.

4. Dependency Injection Strongly Depends on the Spring Container

If you want to use the classes outside the container (such as for unit testing), you have to use the Spring container to instantiate it because there is no other possible way (other than reflection) to set the autowired fields.

Why Doesn't Idea Show a Yellow Warning When @Resource Is on Attribute?

I didn't find the answer in the official document. I checked some materials that said @Autowired is provided by Spring, and once it is switched to another IoC framework, the injection cannot be supported. In contrast, @Resource is provided by JSR-250. It is a Java standard, and the IoC containers we use are compatible with it, so it can work even if containers are changed.

How to Use @Autowired and @Resource

1. Suitable Scenarios for @Autowired and @Resource

Remember @Resource prefers definite and single resources, while @Autowired matches all resources suitable for a type.

For example, you can use @Resource for collection injection. However, we recommend using @Autowired. As seen on the small green label on the left side of Idea, using @Resource to inject collection resources is not recommended. In essence, collection injection is not single and uncertain.

2

2. How to Use @Autowired

Method 1: Use Constructor Injection (Recommended)

Native version:

3

Elegant version: Use @RequiredArgsConstructor + private final of lombok

4

Method 2: Setter Injection

Native version:

5

Elegant version: Use @Setter of lombok

6

Disclaimer: The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.

0 2 0
Share on

Alibaba Cloud Community

877 posts | 198 followers

You may also like

Comments

Alibaba Cloud Community

877 posts | 198 followers

Related Products