1. 개요
이 Spring Framework 기사는 @Resource , @Inject 및 @Autowired 어노테이션 과 같은 종속성 주입과 관련된 어노테이션의 사용을 보여줍니다 . 이러한 어노테이션은 종속성을 해결하는 선언적 방법을 클래스에 제공합니다. 예를 들면 다음과 같습니다.
@Autowired
ArbitraryClass arbObject;
직접 인스턴스화하는 것과는 반대로 (명령 적 방식), 예를 들면 다음과 같습니다.
ArbitraryClass arbObject = new ArbitraryClass();
세 개의 어노테이션 중 두 개는 Java 확장 패키지에 속합니다 : javax.annotation.Resource 및 javax.inject.Inject . @Autowired 어노테이션은에 속하는 org.springframework.beans.factory.annotation의 패키지로 제공된다.
이러한 각 어노테이션은 필드 주입 또는 세터 주입을 통해 종속성을 해결할 수 있습니다. 각 어노테이션에서 가져온 실행 경로를 기반으로 세 가지 어노테이션 간의 차이점을 설명하기 위해 단순화되었지만 실제적인 예제가 사용됩니다.
예제는 통합 테스트 중에 세 가지 주입 어노테이션을 사용하는 방법에 중점을 둡니다. 테스트에 필요한 종속성은 랜덤의 파일 또는 랜덤의 클래스 일 수 있습니다.
2. @Resource 의 nnotation
@Resource의 어노테이션은의 일부입니다 JSR-250 어노테이션 수집 및 자카르타 EE와 함께 제공됩니다. 이 어노테이션에는 우선 순위에 따라 나열된 다음 실행 경로가 있습니다.
- 이름으로 일치
- 유형별 일치
- 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;
이 구성은 이름 별 일치 실행 경로를 사용하여 종속성을 해결합니다. namedFile 빈 은 ApplicationContextTestResourceNameType 애플리케이션 컨텍스트에 정의되어야합니다 .
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 어노테이션 모음. 이 어노테이션에는 우선 순위에 따라 나열된 다음 실행 경로가 있습니다.
- 유형별 일치
- Qualifier 일치
- 이름으로 일치
이러한 실행 경로는 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 어노테이션 과 동일한 실행 경로가 있으며 우선 순위에 따라 나열됩니다.
- 유형별 일치
- Qualifier 일치
- 이름으로 일치
이러한 실행 경로는 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 에서 찾을 수 있습니다 .