1. 개요

이 Spring Framework 기사는 @Resource , @Inject@Autowired 어노테이션 같은 종속성 주입과 관련된 어노테이션의 사용을 보여줍니다 . 이러한 어노테이션은 종속성을 해결하는 선언적 방법을 클래스에 제공합니다. 예를 들면 다음과 같습니다.

@Autowired 
ArbitraryClass arbObject;

직접 인스턴스화하는 것과는 반대로 (명령 적 방식), 예를 들면 다음과 같습니다.

ArbitraryClass arbObject = new ArbitraryClass();

세 개의 어노테이션 중 두 개는 Java 확장 패키지에 속합니다 : javax.annotation.Resourcejavax.inject.Inject . @Autowired 어노테이션은에 속하는 org.springframework.beans.factory.annotation의 패키지로 제공된다.

이러한 각 어노테이션은 필드 주입 또는 세터 주입을 통해 종속성을 해결할 수 있습니다. 각 어노테이션에서 가져온 실행 경로를 기반으로 세 가지 어노테이션 간의 차이점을 설명하기 위해 단순화되었지만 실제적인 예제가 사용됩니다.

예제는 통합 테스트 중에 세 가지 주입 어노테이션을 사용하는 방법에 중점을 둡니다. 테스트에 필요한 종속성은 랜덤의 파일 또는 랜덤의 클래스 일 수 있습니다.

2. @Resourcennotation

@Resource의 어노테이션은의 일부입니다 JSR-250 어노테이션 수집 및 자카르타 EE와 함께 제공됩니다. 이 어노테이션에는 우선 순위에 따라 나열된 다음 실행 경로가 있습니다.

  1. 이름으로 일치
  2. 유형별 일치
  3. Qualifier 일치

이러한 실행 경로는 setter 및 필드 주입 모두에 적용 할 수 있습니다.

2.1. 현장 주입

필드 주입에 의한 종속성 해결은 @Resource 어노테이션으로 인스턴스 변수에 어노테이션을 추가하여 수행됩니다 .

2.1.1. 이름으로 일치

이름 별 일치 필드 삽입을 시연하는 데 사용되는 통합 테스트는 다음과 같습니다.

@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(){
        assertNotNull(defaultFile);
        assertEquals("namedFile.txt", defaultFile.getName());
    }
}

코드를 살펴 보겠습니다. 에서 FieldResourceInjectionTest의 통합 테스트, 선로 (7)에, 이름 의존도의 해상도는에 속성 값으로 Bean 이름으로 전달함으로써 달성된다 @Resource의 어노테이션 :

@Resource(name="namedFile")
private File defaultFile;

이 구성은 이름 별 일치 실행 경로를 사용하여 종속성을 해결합니다. namedFileApplicationContextTestResourceNameType 애플리케이션 컨텍스트에 정의되어야합니다 .

Bean ID와 해당 참조 속성 값이 일치해야합니다.

@Configuration
public class ApplicationContextTestResourceNameType {

    @Bean(name="namedFile")
    public File namedFile() {
        File namedFile = new File("namedFile.txt");
        return namedFile;
    }
}

애플리케이션 컨텍스트에서 Bean을 정의하지 못하면 org.springframework.beans.factory.NoSuchBeanDefinitionException 이 발생합니다. 이는 ApplicationContextTestResourceNameType 애플리케이션 컨텍스트 에서 @Bean 어노테이션에 전달 된 속성 값을 변경하여 입증 할 수 있습니다 . 또는 FieldResourceInjectionTest 통합 테스트 에서 @Resource 어노테이션에 전달 된 속성 값을 변경합니다 .

2.1.2. 유형별 일치

유형별 일치 실행 경로를 보여 주려면 FieldResourceInjectionTest 통합 테스트의 7 행에서 속성 값을 제거하여 다음과 같이 보이도록합니다.

@Resource
private File defaultFile;

테스트를 다시 실행하십시오.

@Resource 어노테이션이 속성 값으로 빈 이름을받지 못하면 Spring Framework는 종속성을 해결하기 위해 다음 수준의 우선 순위 인 유형별 일치를 진행 하므로 테스트는 통과 할 것입니다.

2.1.3. Qualifier 일치

규정 자별 일치 실행 경로를 보여주기 위해 ApplicationContextTestResourceQualifier 애플리케이션 컨텍스트에 정의 된 두 개의 Bean이 있도록 통합 테스트 시나리오가 수정 됩니다.

@Configuration
public class ApplicationContextTestResourceQualifier {

    @Bean(name="defaultFile")
    public File defaultFile() {
        File defaultFile = new File("defaultFile.txt");
        return defaultFile;
    }

    @Bean(name="namedFile")
    public File namedFile() {
        File namedFile = new File("namedFile.txt");
        return namedFile;
    }
}

QualifierResourceInjectionTest 통합 테스트는 경기 별 예선 의존성 해상도를 설명하는 데 사용됩니다. 이 시나리오에서는 특정 빈 종속성을 각 참조 변수에 삽입해야합니다.

@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(){
        assertNotNull(dependency1);
        assertEquals("defaultFile.txt", dependency1.getName());
    }

    @Test
    public void givenResourceQualifier_WhenField_ThenDependency2Valid(){
        assertNotNull(dependency2);
        assertEquals("namedFile.txt", dependency2.getName());
    }
}

통합 테스트를 실행하면 org.springframework.beans.factory.NoUniqueBeanDefinitionException 이 발생합니다. 이 예외는 애플리케이션 컨텍스트가 File 유형의 Bean 정의 두 개를 발견 하고 종속성을 해결해야하는 Bean에 대해 혼동되기 때문에 발생합니다.

이 문제를 해결하려면 QualifierResourceInjectionTest 통합 테스트 의 7 행에서 10 행을 참조하십시오 .

@Resource
private File dependency1;

@Resource
private File dependency2;

다음 코드 줄을 추가합니다.

@Qualifier("defaultFile")

@Qualifier("namedFile")

코드 블록은 다음과 같습니다.

@Resource
@Qualifier("defaultFile")
private File dependency1;

@Resource
@Qualifier("namedFile")
private File dependency2;

통합 테스트를 다시 실행하십시오. 이번에는 통과해야합니다. 이 테스트의 목적은 애플리케이션 컨텍스트에 정의 된 빈이 여러 개 있더라도 @Qualifier 어노테이션이 특정 종속성을 클래스에 주입 할 수 있도록하여 혼동을 없애는 것 입니다.

2.2. 세터 주입

필드에 종속성을 주입 할 때 사용되는 실행 경로는 setter 기반 주입에 적용 할 수 있습니다.

2.2.1. 이름으로 일치

유일한 차이점은 MethodResourceInjectionTest 통합 테스트에 setter 메서드가 있다는 것입니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestResourceNameType.class)
public class MethodResourceInjectionIntegrationTest {

    private File defaultFile;

    @Resource(name="namedFile")
    protected void setDefaultFile(File defaultFile) {
        this.defaultFile = defaultFile;
    }

    @Test
    public void givenResourceAnnotation_WhenSetter_ThenDependencyValid(){
        assertNotNull(defaultFile);
        assertEquals("namedFile.txt", defaultFile.getName());
    }
}

setter 주입에 의한 종속성 해결은 참조 변수의 해당 setter 메서드에 어노테이션을 추가하여 수행됩니다. @Resource 어노테이션에 속성 값으로 Bean 종속성의 이름을 전달하십시오 .

private File defaultFile;

@Resource(name="namedFile")
protected void setDefaultFile(File defaultFile) {
    this.defaultFile = defaultFile;
}

namedFile의 Bean 의존성이 예에서 재사용 될 것입니다. Bean 이름과 해당 속성 값이 일치해야합니다.

통합 테스트를있는 그대로 실행하면 통과합니다.

종속성이 이름 별 일치 실행 경로에 의해 실제로 해결되었는지 확인하려면 @Resource 어노테이션에 전달 된 속성 값을 선택한 값으로 변경 하고 테스트를 다시 실행하십시오. 이번에는 테스트가 NoSuchBeanDefinitionException 과 함께 실패합니다 .

2.2.2. 유형별 일치

setter 기반, 유형별 일치 실행을 보여주기 위해 MethodByTypeResourceTest 통합 테스트를 사용합니다 .

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestResourceNameType.class)
public class MethodByTypeResourceIntegrationTest {

    private File defaultFile;

    @Resource
    protected void setDefaultFile(File defaultFile) {
        this.defaultFile = defaultFile;
    }

    @Test
    public void givenResourceAnnotation_WhenSetter_ThenValidDependency(){
        assertNotNull(defaultFile);
        assertEquals("namedFile.txt", defaultFile.getName());
    }
}

이 테스트를있는 그대로 실행하면 통과합니다.

파일 종속성이 유형별 일치 실행 경로에 의해 실제로 해결 되었는지 확인 하려면 defaultFile 변수의 클래스 유형을 String 과 같은 다른 클래스 유형으로 변경하십시오 . MethodByTypeResourceTest 통합 테스트를 다시 실행하면 이번에는 NoSuchBeanDefinitionException 이 발생합니다.

예외는 유형별 일치가 실제로 파일 종속성 을 해결하는 데 사용되었는지 확인합니다 . NoSuchBeanDefinitionException이의 참조 변수 이름이하지 않는 것을 확인는 빈 이름과 일치해야합니다. 대신 종속성 해결은 참조 변수의 클래스 유형과 일치하는 Bean의 클래스 유형에 따라 다릅니다.

2.2.3. Qualifier 일치

MethodByQualifierResourceTest 통합 테스트는 경기 별 예선 실행 경로를 설명하는 데 사용됩니다 :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestResourceQualifier.class)
public class MethodByQualifierResourceIntegrationTest {

    private File arbDependency;
    private File anotherArbDependency;

    @Test
    public void givenResourceQualifier_WhenSetter_ThenValidDependencies(){
      assertNotNull(arbDependency);
        assertEquals("namedFile.txt", arbDependency.getName());
        assertNotNull(anotherArbDependency);
        assertEquals("defaultFile.txt", anotherArbDependency.getName());
    }

    @Resource
    @Qualifier("namedFile")
    public void setArbDependency(File arbDependency) {
        this.arbDependency = arbDependency;
    }

    @Resource
    @Qualifier("defaultFile")
    public void setAnotherArbDependency(File anotherArbDependency) {
        this.anotherArbDependency = anotherArbDependency;
    }
}

이 테스트의 목적은 특정 유형의 여러 Bean 구현이 애플리케이션 컨텍스트에 정의되어 있더라도 @Qualifier 어노테이션을 @Resource 어노테이션 과 함께 사용 하여 종속성을 해결할 수 있음 을 입증하는 것 입니다.

필드 기반 종속성 주입과 유사하게 애플리케이션 컨텍스트에 정의 된 여러 Bean이있는 경우 종속성을 해결하는 데 사용해야하는 Bean을 지정하는 데 @Qualifier 어노테이션이 사용 되지 않으면 NoUniqueBeanDefinitionException 이 발생합니다 .

3. @Inject 어노테이션

@Inject 어노테이션은에 속하는 JSR-330 어노테이션 모음. 이 어노테이션에는 우선 순위에 따라 나열된 다음 실행 경로가 있습니다.

  1. 유형별 일치
  2. Qualifier 일치
  3. 이름으로 일치

이러한 실행 경로는 setter 및 필드 주입 모두에 적용 할 수 있습니다. @Inject 어노테이션 에 액세스하려면 javax.inject 라이브러리를 Gradle 또는 Maven 종속성으로 선언해야합니다.

Gradle의 경우 :

testCompile group: 'javax.inject', name: 'javax.inject', version: '1'

Maven의 경우 :

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

3.1. Field 주입

3.1.1. 유형별 일치

통합 테스트 예제는 다른 유형의 종속성, 즉 ArbitraryDependency 클래스 를 사용하도록 수정됩니다 . ArbitraryDependency의 클래스 의존성 단지 단순한 의존성 역할 더 이상의 의미를 보유하고있다. 다음과 같이 나열됩니다.

@Component
public class ArbitraryDependency {

    private final String label = "Arbitrary Dependency";

    public String toString() {
        return label;
    }
}

문제의 FieldInjectTest 통합 테스트는 다음과 같이 나열됩니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestInjectType.class)
public class FieldInjectIntegrationTest {

    @Inject
    private ArbitraryDependency fieldInjectDependency;

    @Test
    public void givenInjectAnnotation_WhenOnField_ThenValidDependency(){
        assertNotNull(fieldInjectDependency);
        assertEquals("Arbitrary Dependency",
          fieldInjectDependency.toString());
    }
}

이름으로 종속성을 먼저 해결 하는 @Resource 어노테이션 과 달리 ; @Inject 어노테이션 의 기본 동작은 유형별로 종속성을 해결합니다.

즉, 클래스 참조 변수 이름이 빈 이름과 다르더라도 빈이 애플리케이션 컨텍스트에 정의되어 있으면 종속성이 여전히 해결됩니다. 다음 테스트에서 참조 변수 이름을 확인하십시오.

@Inject
private ArbitraryDependency fieldInjectDependency;

애플리케이션 컨텍스트에 구성된 Bean 이름과 다릅니다.

@Bean
public ArbitraryDependency injectDependency() {
    ArbitraryDependency injectDependency = new ArbitraryDependency();
    return injectDependency;
}

테스트가 실행되면 종속성을 해결할 수 있습니다.

3.1.2. Qualifier 일치

그러나 특정 클래스 유형의 여러 구현이 있고 특정 클래스에 특정 빈이 필요하다면 어떻게 될까요? 다른 종속성이 필요하도록 통합 테스트 예제를 수정하겠습니다.

이 예제에서는 match-by-type 예제에 사용 된 ArbitraryDependency 클래스를 하위 클래스로 지정 하여 AnotherArbitraryDependency 클래스 를 만듭니다 .

public class AnotherArbitraryDependency extends ArbitraryDependency {

    private final String label = "Another Arbitrary Dependency";

    public String toString() {
        return label;
    }
}

각 테스트 케이스의 목적은 각 종속성이 각 참조 변수에 올바르게 주입되도록하는 것입니다.

@Inject
private ArbitraryDependency defaultDependency;

@Inject
private ArbitraryDependency namedDependency;

FieldQualifierInjectTest에 다음과 같이 규정 자에 의해 경기를 보여주기 위해 사용되는 통합 테스트가 나열되어 있습니다 :

@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(){
        assertNotNull(defaultDependency);
        assertEquals("Arbitrary Dependency",
          defaultDependency.toString());
    }

    @Test
    public void givenInjectQualifier_WhenOnField_ThenNamedFileValid(){
        assertNotNull(defaultDependency);
        assertEquals("Another Arbitrary Dependency",
          namedDependency.toString());
    }
}

애플리케이션 컨텍스트에 특정 클래스의 여러 구현이 있고 FieldQualifierInjectTest 통합 테스트가 아래 나열된 방식으로 종속성을 주입하려고 시도하는 경우 :

@Inject 
private ArbitraryDependency defaultDependency;

@Inject 
private ArbitraryDependency namedDependency;

NoUniqueBeanDefinitionException가 발생합니다.

이 예외를 던지는 것은 특정 클래스의 여러 구현이 있고 어떤 클래스를 사용할지 혼란 스럽다는 것을 지적하는 Spring Framework의 방법입니다. 혼동을 해명하려면 FieldQualifierInjectTest 통합 테스트 의 7 행과 10 행으로 이동하십시오 .

@Inject
private ArbitraryDependency defaultDependency;

@Inject
private ArbitraryDependency namedDependency;

@Inject 어노테이션 과 함께 사용되는 @Qualifier 어노테이션에 필수 Bean 이름을 전달하십시오 . 이제 코드 블록은 다음과 같습니다.

@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;

@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;

@Qualifier의 빈 이름을 수신 할 때 어노테이션 엄격한 일치를 기대하고있다. Bean 이름이 규정 자에 올바르게 전달되었는지 확인하십시오 . 그렇지 않으면 NoUniqueBeanDefinitionException 이 발생합니다. 테스트를 다시 실행하면 이번에는 통과해야합니다.

3.1.3. 이름으로 일치

FieldByNameInjectTest의 이름으로 일치를 설명하는 데 사용되는 통합 테스트 유형의 실행 경로에 의한 경기와 유사하다. 유일한 차이점은 이제 특정 유형이 아닌 특정 Bean이 필요하다는 것입니다. 이 예제에서는 ArbitraryDependency 클래스를 다시 하위 클래스로 지정하여 YetAnotherArbitraryDependency 클래스 를 생성합니다 .

public class YetAnotherArbitraryDependency extends ArbitraryDependency {

    private final String label = "Yet Another Arbitrary Dependency";

    public String toString() {
        return label;
    }
}

이름 별 일치 실행 경로를 보여주기 위해 다음 통합 테스트를 사용합니다.

@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(){
        assertNotNull(yetAnotherFieldInjectDependency);
        assertEquals("Yet Another Arbitrary Dependency",
          yetAnotherFieldInjectDependency.toString());
    }
}

애플리케이션 컨텍스트는 다음과 같이 나열됩니다.

@Configuration
public class ApplicationContextTestInjectName {

    @Bean
    public ArbitraryDependency yetAnotherFieldInjectDependency() {
        ArbitraryDependency yetAnotherFieldInjectDependency =
          new YetAnotherArbitraryDependency();
        return yetAnotherFieldInjectDependency;
    }
}

통합 테스트를있는 그대로 실행하면 통과합니다.

종속성이 이름 별 일치 실행 경로에 의해 실제로 주입되었는지 확인 하려면 @Named 어노테이션 에 전달 된 yetAnotherFieldInjectDependency을 원하는 다른 이름으로 변경합니다. 테스트를 다시 실행하십시오 . 이번에NoSuchBeanDefinitionException 이 발생합니다.

3.2. 세터 주입

용 세터 기반 주입 @Inject 어노테이션이 사용되는 방식과 유사한 @Resource의 세터 기반 사출. 참조 변수에 어노테이션을 추가하는 대신 해당 setter 메서드에 어노테이션이 추가됩니다. 필드 기반 종속성 주입이 뒤 따르는 실행 경로는 setter 기반 주입에도 적용됩니다.

4. @Autowired 어노테이션

@Autowired 어노테이션 의 동작은 @Inject 어노테이션 과 유사합니다 . 유일한 차이점은 @Autowired 어노테이션이 Spring 프레임 워크의 일부라는 것입니다. 이 어노테이션에는 @Inject 어노테이션 과 동일한 실행 경로가 있으며 우선 순위에 따라 나열됩니다.

  1. 유형별 일치
  2. Qualifier 일치
  3. 이름으로 일치

이러한 실행 경로는 setter 및 필드 주입 모두에 적용 할 수 있습니다.

4.1. 현장 주입

4.1.1. 유형별 일치

@Autowired 유형별 일치 실행 경로 를 보여주는 데 사용되는 통합 테스트 예제 @Inject 유형별 일치 실행 경로 를 보여주는 데 사용되는 테스트와 유사 합니다. FieldAutowiredTest의 통합 테스트는 경기 별 유형 사용하여 설명하는 데 사용 @Autowired 다음과 같이 어노테이션이 나열되어 있습니다 :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestAutowiredType.class)
public class FieldAutowiredIntegrationTest {

    @Autowired
    private ArbitraryDependency fieldDependency;

    @Test
    public void givenAutowired_WhenSetOnField_ThenDependencyResolved() {
        assertNotNull(fieldDependency);
        assertEquals("Arbitrary Dependency", fieldDependency.toString());
    }
}

이 통합 테스트에 대한 애플리케이션 컨텍스트는 다음과 같이 나열됩니다.

@Configuration
public class ApplicationContextTestAutowiredType {

    @Bean
    public ArbitraryDependency autowiredFieldDependency() {
        ArbitraryDependency autowiredFieldDependency =
          new ArbitraryDependency();
        return autowiredFieldDependency;
    }
}

통합 테스트의 목적은 유형별 일치가 다른 실행 경로보다 우선 순위가 높다는 것을 입증하는 것입니다. FieldAutowiredTest 통합의 8 행 에서 참조 변수 이름이 어떻게 테스트되는지 확인하십시오.

@Autowired
private ArbitraryDependency fieldDependency;

애플리케이션 컨텍스트의 Bean 이름과 다릅니다.

@Bean
public ArbitraryDependency autowiredFieldDependency() {
    ArbitraryDependency autowiredFieldDependency =
      new ArbitraryDependency();
    return autowiredFieldDependency;
}

테스트가 실행되면 통과합니다.

유형별 일치 실행 경로를 사용하여 종속성이 실제로 해결되었는지 확인하려면 fieldDependency 참조 변수 의 유형을 변경 하고 통합 테스트를 다시 실행하십시오. 이번에는 FieldAutowiredTest 통합 테스트가 실패해야하며 NoSuchBeanDefinitionException 이 발생합니다. 이는 유형별 일치가 종속성을 해결하는 데 사용되었는지 확인합니다.

4.1.2. Qualifier 일치

아래 나열된 것과 같이 애플리케이션 컨텍스트에서 여러 Bean 구현이 정의 된 상황에 직면하면 어떻게 될까요?

@Configuration
public class ApplicationContextTestAutowiredQualifier {

    @Bean
    public ArbitraryDependency autowiredFieldDependency() {
        ArbitraryDependency autowiredFieldDependency =
          new ArbitraryDependency();
        return autowiredFieldDependency;
    }

    @Bean
    public ArbitraryDependency anotherAutowiredFieldDependency() {
        ArbitraryDependency anotherAutowiredFieldDependency =
          new AnotherArbitraryDependency();
        return anotherAutowiredFieldDependency;
    }
}

는 IF FieldQualifierAutowiredTest의 아래 통합 테스트, 실행 :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestAutowiredQualifier.class)
public class FieldQualifierAutowiredIntegrationTest {

    @Autowired
    private ArbitraryDependency fieldDependency1;

    @Autowired
    private ArbitraryDependency fieldDependency2;

    @Test
    public void givenAutowiredQualifier_WhenOnField_ThenDep1Valid(){
        assertNotNull(fieldDependency1);
        assertEquals("Arbitrary Dependency", fieldDependency1.toString());
    }

    @Test
    public void givenAutowiredQualifier_WhenOnField_ThenDep2Valid(){
        assertNotNull(fieldDependency2);
        assertEquals("Another Arbitrary Dependency",
          fieldDependency2.toString());
    }
}

NoUniqueBeanDefinitionException가 발생합니다.

예외는 애플리케이션 컨텍스트에 정의 된 두 개의 Bean으로 인한 모호성 때문입니다. Spring Framework는 어떤 빈 의존성이 어떤 참조 변수에 자동 연결되어야하는지 알지 못합니다. FieldQualifierAutowiredTest 통합 테스트 의 7 행과 10 행에 @Qualifier 어노테이션을 추가하여이 문제를 해결하십시오 .

@Autowired
private FieldDependency fieldDependency1;

@Autowired
private FieldDependency fieldDependency2;

코드 블록은 다음과 같습니다.

@Autowired
@Qualifier("autowiredFieldDependency")
private FieldDependency fieldDependency1;

@Autowired
@Qualifier("anotherAutowiredFieldDependency")
private FieldDependency fieldDependency2;

테스트를 다시 실행하면 이번에는 통과합니다.

4.1.3. 이름으로 일치

@Autowired 어노테이션을 사용하여 필드 종속성을 삽입 할 때 동일한 통합 테스트 시나리오를 사용하여 이름 별 일치 실행 경로를 보여줍니다 . 이름으로 종속성을 자동 연결하는 경우 @ComponentScan 어노테이션을 애플리케이션 컨텍스트 인 ApplicationContextTestAutowiredName 과 함께 사용해야합니다 .

@Configuration
@ComponentScan(basePackages={"com.baeldung.dependency"})
    public class ApplicationContextTestAutowiredName {
}

@ComponentScan 어노테이션은 어노테이션이 추가 된 자바 클래스 패키지를 검색합니다 @Component 어노테이션. 예를 들어, 응용 프로그램 컨텍스트에서 com.baeldung.dependency 패키지는 @Component 어노테이션 으로 어노테이션이 달린 클래스를 검색합니다 . 이 시나리오에서 Spring Framework는 @Component 어노테이션 이있는 ArbitraryDependency 클래스를 감지해야합니다 .

@Component(value="autowiredFieldDependency")
public class ArbitraryDependency {

    private final String label = "Arbitrary Dependency";

    public String toString() {
        return label;
    }
}

@Component 어노테이션에 전달 된 속성 값 autowiredFieldDependency 는 Spring Framework에 ArbitraryDependency 클래스가 autowiredFieldDependency 라는 구성 요소 임을 알려줍니다 . 위해서는 @Autowired 이름으로 해결 종속성에 대한 어노테이션에 정의 필드 이름과 일치해야합니다 구성 요소 이름 FieldAutowiredNameTest의 통합 테스트; 8 행을 참조하십시오.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  loader=AnnotationConfigContextLoader.class,
  classes=ApplicationContextTestAutowiredName.class)
public class FieldAutowiredNameIntegrationTest {

    @Autowired
    private ArbitraryDependency autowiredFieldDependency;

    @Test
    public void givenAutowiredAnnotation_WhenOnField_ThenDepValid(){
        assertNotNull(autowiredFieldDependency);
        assertEquals("Arbitrary Dependency",
          autowiredFieldDependency.toString());
	}
}

FieldAutowiredNameTest의 있는 그대로 통합 테스트가 실행되고, 그것을 전달합니다.

그러나 @Autowired 어노테이션이 실제로 이름 별 일치 실행 경로를 호출 했는지 어떻게 알 수 있습니까? 참조 변수 autowiredFieldDependency의 이름을 선택한 다른 이름으로 변경 한 다음 테스트를 다시 실행합니다.

이번에는 테스트가 실패하고 NoUniqueBeanDefinitionException 이 발생합니다. 유사한 검사는 @Component 속성 값 autowiredFieldDependency 를 선택한 다른 값으로 변경하고 테스트를 다시 실행하는 것입니다. NoUniqueBeanDefinitionException는 또한 발생합니다.

이 예외는 잘못된 빈 이름이 사용되면 유효한 빈을 찾을 수 없다는 증거입니다. 따라서 이름 별 일치 실행 경로가 호출되었습니다.

4.2. 세터 주입

용 세터 기반 주입 @Autowired 어노테이션 입증 접근법과 유사한 @Resource의 세터 기반 사출. @Inject 어노테이션으로 참조 변수에 어노테이션을 추가하는 대신 해당 setter에 어노테이션이 추가됩니다. 필드 기반 종속성 주입이 뒤 따르는 실행 경로는 setter 기반 주입에도 적용됩니다.

5. 이러한 어노테이션 적용

이로 인해 어떤 어노테이션을 사용해야하며 어떤 상황에서 사용해야합니까? 이러한 질문에 대한 답은 해당 애플리케이션이 직면 한 설계 시나리오와 개발자가 각 어노테이션의 기본 실행 경로를 기반으로 다형성을 활용하려는 방법에 따라 다릅니다.

5.1. 다형성을 통한 애플리케이션 전체의 싱글 톤 사용

애플리케이션 동작이 인터페이스 또는 추상 클래스의 구현을 기반으로하는 디자인이고 이러한 동작이 애플리케이션 전체에서 사용되는 경우 @Inject 또는 @Autowired 어노테이션 을 사용합니다 .

이 접근 방식의 이점은 응용 프로그램을 업그레이드하거나 버그를 수정하기 위해 패치를 적용해야한다는 것입니다. 그런 다음 전체 애플리케이션 동작에 대한 부정적인 영향을 최소화하면서 클래스를 교체 할 수 있습니다. 이 시나리오에서 기본 기본 실행 경로는 유형별 일치입니다.

5.2. 다형성을 통한 세분화 된 애플리케이션 동작 구성

애플리케이션이 복잡한 동작을 갖는 디자인 인 경우 각 동작은 서로 다른 인터페이스 / 추상 클래스를 기반으로하며 이러한 각 구현의 사용법은 애플리케이션에 따라 다르므로 @Resource 어노테이션 을 사용하십시오 . 이 시나리오에서 기본 기본 실행 경로는 이름 별 일치입니다.

5.3. 종속성 주입은 Jakarta EE 플랫폼에서만 처리해야합니다.

Spring이 아닌 Jakarta EE Platform에서 모든 종속성을 주입해야하는 설계 요구 사항이있는 경우 @Resource 어노테이션과 @Inject 어노테이션 중에서 선택할 수 있습니다. 필요한 기본 실행 경로를 기준으로 두 어노테이션 사이의 최종 결정 범위를 좁혀 야합니다.

5.4. 의존성 주입은 Spring 프레임 워크에 의해서만 처리되어야합니다.

모든 종속성이 Spring Framework에서 처리되어야하는 의무가있는 경우 유일한 선택은 @Autowired 어노테이션입니다.

5.5. 토론 요약

아래 표는 논의 내용을 요약 한 것입니다.

대본 @자원 @ 주입 @Autowired
다형성을 통해 응용 프로그램 전체에서 싱글 톤 사용
다형성을 통한 세분화 된 애플리케이션 동작 구성
종속성 주입은 Jakarta EE 플랫폼에서만 처리해야합니다.
의존성 주입은 Spring Framework에 의해서만 처리되어야합니다.

6. 결론

이 기사는 각 어노테이션의 동작에 대한 더 깊은 통찰력을 제공하는 것을 목표로했습니다. 각 어노테이션의 작동 방식을 이해하면 전반적인 애플리케이션 설계 및 유지 관리에 도움이됩니다.

토론 중에 사용 된 코드는 GitHub 에서 찾을 수 있습니다 .