Talk about dependency injection annotation @ Resource and @ Autowired

Keywords: Java Spring Attribute

1. Preface

@Both Resource and @ Autowired annotations can be used for declarative dependency injection in Spring Framework applications. And the interview often involves these two notes of knowledge. Let's summarize them today.

2. @Resource

Full name javax.annotation.Resource , which is an annotation of the JSR-250 specification, including Jakarta EE (J2EE). Spring provides support for this annotation. Let's take a closer look at the rules of this annotation.

This annotation is used on member properties and setter methods. By default, @ Resource is injected by name. If the name is not explicitly declared, it is injected by variable name or the corresponding parameter name in the method.

If we want to embody polymorphism in the target Bean, we can write as follows:

/**
 * The manifestation of polymorphism
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class ResourceTest {
    @Resource
    private ApplicationRunner applicationRunner;    
    @Resource
    private ApplicationRunner runner;
    // ...
}

Qualifier constraints see Detailed analysis of Spring annotation @ Qualifier

3. @Autowired

@Autowired is usually applied to constructors, member variables, and methods. Its mechanism is as follows:

We need to have a good chat about this annotation, which is used quite frequently.

3.1 mark on structure

The corresponding Bean can be injected by labeling the constructor of the target Bean.

package cn.felord;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * @author felord.cn
 * @since 9:26
 **/
@Component
public class AutowiredTest {
 private final ApplicationRunner applicationRunner;

    @Autowired
    public AutowiredTest(ApplicationRunner applicationRunner) {
        this.applicationRunner = applicationRunner;
    }
}

Starting with Spring Framework 4.3, @ Autowired if the target Bean defines only one constructor, you no longer need to add the @ Autowired annotation to the constructor. If several constructors are available for the target Bean and there is no primary / default constructor, at least one must be marked @ Autowired to indicate which constructor the Spring IoC container uses.

3.2 mark on member variable

Like @ Resource, @ Autowired can also be labeled on the member variables of the target Bean.

/**
 * @author felord.cn
 * @since 9:26
 **/
@Component
public class AutowiredTest {
    @Autowired
    private ApplicationRunner applicationRunner;
    
    // ...
    
}

3.3 mark on method

There are many common setter methods. And one @ Autowired supports injecting multiple parameters.

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {

    private ApplicationRunner applicationRunner;
    private EmployeeMapper employeeMapper;
    private DepartmentMapper departmentMapper;

    /**
     * Sets application runner.
     *
     * @param applicationRunner the application runner
     */
    @Autowired
    public void setApplicationRunner(ApplicationRunner applicationRunner) {
        this.applicationRunner = applicationRunner;
    }


    /**
     * Support for multiple parameters
     *
     * @param employeeMapper   the employee mapper
     * @param departmentMapper the department mapper
     */
    @Autowired
    public void prepare(EmployeeMapper employeeMapper, DepartmentMapper departmentMapper) {
        this.employeeMapper = employeeMapper;
        this.departmentMapper = departmentMapper;
    }

}

You think it's over? Most people don't care.

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
    // Injection array
    @Autowired
    private MovieCatalog[] movieCatalogs;
    
    private Map<String, Movie> movies;
    
    private Set<CustomerPreferenceDao> customerPreferenceDaos;
    
    // Injection set
    @Autowired
    public MovieRecommender(Set<CustomerPreferenceDao> customerPreferenceDaos) {
        this.customerPreferenceDaos = customerPreferenceDaos;
    }
            
    // Inject map 
    @Autowired
    public void setMovieCatalogs(Map<String, Movie> movies) {
        this.movies = movies;
    }
   
    // ...
}

The Bean can be injected into the array and collection container of the target Bean. By default, automatic assembly fails when no matching candidate beans are available for a given injection point. There should be at least one matching element.

If you want elements to be Ordered in a specific Order, the element Bean can implement org.springframework.core.Ordered interface or corresponding annotation @ Order or standard @ Priority. Based on some mechanisms, it is not recommended to use annotation to sort. Otherwise, it cannot meet the expected expectation. The interface Ordered is recommended.

3.4 optional assembly

@Resource does not provide the feature of optional assembly. If it cannot assemble, it will throw an exception. However, @ Autowired provides the required property (the default value is true) to avoid this situation. Set @ Autowired to false.

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
    // Once the movieFinder is not found, it will not be abnormal and initialized to null
    @Autowired(required = false)
    private MovieFinder movieFinder;
    // ...
}

There are also operations here. You can ignore the required attribute. Through Java 8 java.util.Optional To indicate that the candidate Bean is optional.

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
public class SimpleMovieLister {
    // Use Optional to indicate that the candidate Bean is Optional
    @Autowired
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
     //   ...
    }
}

Starting from Spring 5.0, you can also use @ nullable annotation, which can be used to implement your own detection logic or directly provided by JSR-305 javax.annotation.Nullable .

/**
 * The type Autowired test.
 *
 * @author felord.cn
 * @since 9 :26
 */
@Component
public class AutowiredTest {
public class SimpleMovieLister {
    // Use @ Nullable annotation to indicate the candidate Bean is optional
    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
      //  ...
    }
}

4. @Inject

Starting with Spring 3.0, Spring provides support for JSR-330 standard annotations (dependency injection). You need to introduce dependency:

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

Then you can use the relevant annotations for dependency injection. The main annotations are@ javax.inject.Inject . In most cases, the annotation can be used instead of @ Autowired, but @ inject does not have the required attribute, but it can also be used with java.util.Optional Or use @ Nullable to achieve the same effect.

In most cases, no one likes to introduce additional Jakarta EE dependency to use an existing function. Spring blocks the ecosystem injected by Jakarta EE dependency.

5. Summary

@The priority order of Resource and @ Autowired is different (see the figure above). In addition, @ Resource belongs to the Jakarta EE specification and @ Autowired belongs to the Spring category, @ Resource cannot be used in the construction parameter, @ Autowired supports the required attribute. From the perspective of object-oriented, @ Resource is more suitable for fine-grained injection of polymorphism, while @ Autowired focuses more on single instance injection of polymorphism. @Inject, on the other hand, doesn't need to discuss it too much, just as an addition. Well, here we are today, pay more attention to: small fat brother, more knowledge sharing of dry goods.

Pay attention to the official account: Felordcn for more information

Personal blog: https://felord.cn

Posted by stratguitar on Sun, 07 Jun 2020 19:06:28 -0700