문제 발생
Github에서 다른 분들이 작업한 프로젝트를 보며 공부를 하던 중 Service를 interface로 만든 뒤 구현을 ServiceImpl로 만든 뒤 사용하는 것을 보게 되었습니다. 저는 Service를 바로 클래스로 구현을 해서 사용하는 중이기 때문에 왜 Service를 interface로 만들어서 사용하는지 궁금했습니다.
그래서 찾아보니 이는 예전부터 Spring을 사용해오던 사람들과 또는 그로부터 Spring을 배우게 된 분들이 주로 사용하게 되는데 예전에 Spring은 proxy를 생성할 때에 interface 타입만을 사용하여 proxy를 생성할 수 있었고 이를 주입받아서 사용해야 했습니다. 하지만 요즘은 class 타입을 이용하여도 proxy를 생성할 수 있고 이를 이용해서 주입받아서 사용할 수 있습니다. 하지만 관습처럼 사용해 오던 interface를 이용한 Service 생성 방식 계속해서 사용하는 것으로 볼 수 있습니다. ( 물론 interface를 이용한 Service생성 방식은 코드를 유연하게 작성할 수 있다는 이점이 있다고 생각합니다. )
위의 내용은 application.properties에서 아래와 같이 설정을 할 수 있습니다. 만약 기본값인 true로 놓아둔다면 class 타입을 이용한 proxy 타입을 사용할 수 있기 때문에 interface를 사용하지 않아도 되지만 만약 임의로 false로 설정을 한다면 interface를 이용해 Service를 만든 뒤 ServiceImpl로 구현을 하고 사용을 해야되게 됩니다.
spring.aop.proxy-target-class=false;
spring.aop.proxy-target-class=true; //default
아무튼 위의 내용을 확인하고 만약 interface 사용하는 상황에서의 코드를 살펴보다 보니 아래와 같은 상황이 궁금해졌습니다.
//MyTest.java
package fftl.lookupBoard.service;
public interface MyTest {
Integer MyCalculate(int a, int b);
}
//MyTestT1
package fftl.lookupBoard.service;
import org.springframework.stereotype.Service;
@Service
public class MyTestT1 implements MyTest{
@Override
public Integer MyCalculate(int a, int b) {
return a*10 + b*10;
}
}
//MyTestT2
package fftl.lookupBoard.service;
import org.springframework.stereotype.Service;
@Service
public class MyTestT2 implements MyTest{
@Override
public Integer MyCalculate(int a, int b){
return a+b;
}
}
위와 같은 MyTest가 존재하고 이를 기반으로 만든 두 개의 MyTestT1, MyTestT2가 존재한다면 MyTest의 MyCalculate를 사용할 때 어떤 MyCalculate가 실행이 되는지 궁금했습니다. 그래서 만들고 있던 프로젝트에서 잠깐 테스트를 진행해 보았습니다.
실행시켰더니 아래와 같이 NoUniqueBeanDefinitionException 과 함께 하나의 Bean과 매칭이 가능한데 두 개가 발견되었다는 문제가 나타났습니다.
이에 대한 해결 방법을 찾아보았고 몇가지의 방법이 있다는 것을 알게 되었습니다.
1. 의존성을 주입 할 때에 구현 클래스인 MyTestT1 또는 MyTestT2를 직접 주입하여 사용하는 것 입니다.
2. 의존성을 주입 할 때에 MyTest 인터페이스를 주입 하되 필드의 이름을 bean 이름인 myTestT1, 또는 myTestT2를 사용하면 해당 클래스를 주입받을 수 있습니다.
3. @Qualifier 또는 @Primary 어노테이션을 사용하여 우선권을 줍니다.
자세한 설명은 출처 링크에 가시면 자세하게 확인하실 수 있습니다. 아무튼 Spring 에서 어떠한 기준으로 두가지 이상의 Bean을 가진 인터페이스에는 어떻게 대응을 하는지 궁금했고 방법에 대해서 생각해보는 시간을 가지게 되었습니다. 이상입니다.
출처
'Study > Spring' 카테고리의 다른 글
[Spring] @RequiredArgsConstructor 이란? (0) | 2022.03.06 |
---|---|
[Spring] null check 잊지 않기, 메모는 바로바로 하기 (0) | 2022.01.31 |
[Spring] data.sql으로 입력된 데이터 9시간 차이 문제 (1) | 2022.01.28 |
[Spring] Spring Boot data.sql 적용 안됨 문제 (0) | 2022.01.28 |
[Spring Security] Spring Security 500 error page ( "status" : 999 ) (0) | 2021.01.02 |