@TOC

This article Outlines the differences between annotations commonly used in these three Spring applications.

@Resources

@Resources:

The @Resource annotation is part of the JSR-250 annotation collection and is packaged with Jakarta EE.

What is jSR-250? Visit this link: jcp.org/en/jsr/deta…

There are many PDFS to download:

When you open it, you’ll see a document of Java supported annotations. These documents are the most authoritative:

As documented, @Resources injection of beans takes the following priority:

  1. Match by Name
  2. Match by Type
  3. Match by Qualifier

Match by Name

Let’s look at the Match by Name example. The following code attempts to inject a Bean named namedFile with Match by Name:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestResourceNameType.class)
public class FieldResourceInjectionIntegrationTest {
 
    @Resource(name="namedFile")
    private File defaultFile;
 
    @Test
    public void givenResourceAnnotation_WhenOnField_ThenDependencyValid(a){
        assertNotNull(defaultFile);
        assertEquals("namedFile.txt", defaultFile.getName()); }}Copy the code

The Bean is defined in the following code:

@Configuration
public class ApplicationContextTestResourceNameType {
 
    @Bean(name="namedFile")
    public File namedFile(a) {
        File namedFile = new File("namedFile.txt");
        returnnamedFile; }}Copy the code

At run time, the Name attribute of the @resource at the declared Bean dependency matches the Name attribute of the @bean at the Bean definition, and the Match by Name test passes.

Match by Type

Remove the name attribute from the @Resource annotation in the consumer code that uses the bean and make it look like this:

@Resource
private File defaultFile;
Copy the code

The test still passes because the Match by Name detection mechanism fails, and the next round of Match by Type detection succeeds.

Match by Qualifier

Define two beans:

@Configuration
public class ApplicationContextTestResourceQualifier {
 
    @Bean(name="defaultFile")
    public File defaultFile(a) {
        File defaultFile = new File("defaultFile.txt");
        return defaultFile;
    }
 
    @Bean(name="namedFile")
    public File namedFile(a) {
        File namedFile = new File("namedFile.txt");
        returnnamedFile; }}Copy the code

Test code:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestResourceQualifier.class)
public class QualifierResourceInjectionIntegrationTest {
 
    @Resource
    private File dependency1;
     
    @Resource
    private File dependency2;
 
    @Test
    public void givenResourceAnnotation_WhenField_ThenDependency1Valid(a){
        assertNotNull(dependency1);
        assertEquals("defaultFile.txt", dependency1.getName());
    }
 
    @Test
    public void givenResourceQualifier_WhenField_ThenDependency2Valid(a){
        assertNotNull(dependency2);
        assertEquals("namedFile.txt", dependency2.getName()); }}Copy the code

Failed to perform this time, I met abnormal org. Springframework. Beans. Factory. NoUniqueBeanDefinitionException.

The reason is that the Name of the injected Bean was not specified in our test code, so Spring’s Match by Name detection failed. During the Match by Type detection, two beans of the same Type were detected, and the Spring framework did not know which Bean to inject, so an exception was reported.

It is also easy to avoid this exception using @qualifier. The code is as follows:


@Resource
@Qualifier("defaultFile")
private File dependency1;
 
@Resource
@Qualifier("namedFile")
private File dependency2;
Copy the code

@Inject

This annotation is defined in JSR-330, linked to the document:

Jcp.org/en/jsr/deta…

Injection priority:

  1. Match by Type
  2. Match by Qualifier
  3. Match by Name

Match by Type

Notice The highest priority of @inject is Match by Type, not Match by Name of @resource.

Define an arbitrary Component to inject:

@Component
public class ArbitraryDependency {
 
    private final String label = "Arbitrary Dependency";
 
    public String toString(a) {
        returnlabel; }}Copy the code

Inject:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestInjectType.class)
public class FieldInjectIntegrationTest {
 
    @Inject
    private ArbitraryDependency fieldInjectDependency;
 
    @Test
    public void givenInjectAnnotation_WhenOnField_ThenValidDependency(a){
        assertNotNull(fieldInjectDependency);
        assertEquals("Arbitrary Dependency", fieldInjectDependency.toString()); }}Copy the code

Match by Qualifier

Define a new component to inject:

public class AnotherArbitraryDependency extends ArbitraryDependency {
 
    private final String label = "Another Arbitrary Dependency";
 
    public String toString(a) {
        returnlabel; }}Copy the code

Test code:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestInjectQualifier.class)
public class FieldQualifierInjectIntegrationTest {
 
    @Inject
    private ArbitraryDependency defaultDependency;
 
    @Inject
    private ArbitraryDependency namedDependency;
 
    @Test
    public void givenInjectQualifier_WhenOnField_ThenDefaultFileValid(a){
        assertNotNull(defaultDependency);
        assertEquals("Arbitrary Dependency",
          defaultDependency.toString());
    }
 
    @Test
    public void givenInjectQualifier_WhenOnField_ThenNamedFileValid(a){
        assertNotNull(defaultDependency);
        assertEquals("Another Arbitrary Dependency", namedDependency.toString()); }}Copy the code

And before @ the Resource for the first time by trying to Match by Type failure injection, encounter exceptions: NoUniqueBeanDefinitionException

Use @qualifier to avoid this exception:

@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;
 
@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;
Copy the code

Match by Name

public class YetAnotherArbitraryDependency extends ArbitraryDependency {
 
    private final String label = "Yet Another Arbitrary Dependency";
 
    public String toString(a) {
        returnlabel; }}Copy the code

Consumer Code:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestInjectName.class)
public class FieldByNameInjectIntegrationTest {
 
    @Inject
    @Named("yetAnotherFieldInjectDependency")
    private ArbitraryDependency yetAnotherFieldInjectDependency;
 
    @Test
    public void givenInjectQualifier_WhenSetOnField_ThenDependencyValid(a){
        assertNotNull(yetAnotherFieldInjectDependency);
        assertEquals("Yet Another Arbitrary Dependency", yetAnotherFieldInjectDependency.toString()); }}Copy the code

Application Context code:

@Configuration
public class ApplicationContextTestInjectName {
 
    @Bean
    public ArbitraryDependency yetAnotherFieldInjectDependency(a) {
        ArbitraryDependency yetAnotherFieldInjectDependency =
          new YetAnotherArbitraryDependency();
        returnyetAnotherFieldInjectDependency; }}Copy the code

The test pass

@Autowired

This annotation is used in the same way as @inject, the only difference being that @AutoWired belongs to the annotation provided by the Spring framework. Example slightly.

For more of Jerry’s original articles, please follow the public account “Wang Zixi “: