[Spring] ServiceImpl 클래스 @RequiredArgsConstructor로 의존성 주입하기

DDRRDDDD·2023년 6월 8일
0
post-thumbnail

개요

개인 프로젝트 중 엑셀 파일을 다룰 일이 있었다. Apache POI 라이브러리를 활용하여 코딩을 시작할려하니 CSV 파일 처리에 대해 고려해야 했고 이를 POI로 해결하기엔 비효율적일 수 있어 잠시 보류 해야했다.

이를 위해 코드도 열려 있는 코드를 작성해야한다 생각했고, 유지보수가 용이할 수 있게 Controller 클래스가 구현체에 의존하지 않게 Service 인터페이스를 의존하게 하여 코드 확장 가능성을 열어 두었다.


1. 스프링 의존성 주입 방법

의존성 주입의 종류로는 Constructor(생성자), Setter, Field 가 있다.

  1. Constructor(생성자)
@Controller
public class POIController{
	private POIService poiSerivce;
    
    @Autowired
    public POIController(POIService poiService){
    	this.poiService = poiService;
    }
}
  1. Setter
@Controller
public class POIController{
	private POIService poiSerivce;
    
    @Autowired
    public void setPoiController(POIService poiService){
    	this.poiService = poiService;
    }
}
  1. Field
@Controller
public class POIController{
	@Autowired
	private POIService poiSerivce;
}

또한 lombok라이브러리 @RequiredArgsConstructor를 활용하여 생성자를 통해 의존성을 주입 받을 수 있다.

@Controller
@RequiredArgsConstructor
public class POIController{
	//final 
	private final POIService poiSerivce;
}

스프링(Spring4.0 이상)은 생성자주입 방식을 권장하고 이처럼 3.Field방식처럼 코드가 간결할 뿐만 아니라 생성자를 통해 의존성을 주입할 수 있게 해준다

하지만 field 주입은 권장하지 않기에 굉장히 이점이 많다 그리고 난 이 방법을 사용할거다

생성자 주입 방식을 사용하는 이유

  1. 명확한 의존성 표현
  2. 불변성과 불변성 보장
  3. 테스트 용이성
  4. 순환 참조 방지
  5. 코드 품질 및 가독성

2. Service 인터페이스를 구현한 ServiceImpl 클래스

public interface POIService {
	// 기타 등등
    public void excelUpload();
}
@Service
public class POIServiceImplA implements POIService{
	@Override
    public void excelUpload(){
    	System.out.println("POI A를 호출");
       
       	//내부 로직
    }
}

```java
@Service
public class POIServiceImplB implements POIService{
	@Override
    public void excelUpload(){
    	System.out.println("POI B를 호출");
        
        // 내부 로직
    }
}

앞서 말한거 처럼 구현체를 의존하지 않게 위와 같이 코드를 짜보았다고 가정하자

하지만 문제가 있는데

이처럼 POIService에 @RequiredArgsConstructor 어노테이션이 적용되지 않는걸 볼 수 있다
구현체가 하나가 있으면 문제가 생기지 않는데 두개 이상일 경우에는 A와 B 중 어느 클래스를 주입해야하는지 애매모호해진다

@Controller
public class POIController{
	private POIService poiSerivce;
    
    @Autowired
    public void setPoiController(POIServiceA poiServiceA){
    	this.poiService = poiServiceA;
    }
}

@Autowired를 사용하여 생성자의 파라미터를 지정하여 사용할 수 있지만 나는 @RequiredArgsConstructor로 충분히 가능할거 같았고 방법을 찾아 보았다.


3. @Primary

말한거 처럼 @RequiredArgsConstructor를 사용하면 스프링은 어떤 클래스를 주입해야하는지 모른데 그래서 @Primary를 사용하여 문제를 해결하였다.

@Primary 어노테이션을 붙여주면 자동적으로 해당 빈이 선택된다. 주입 받을 때마다 모든 코드에 @Qualifier 어노테이션을 붙여줘야하는 Qualifier 방법보다 간단하다.

@Primary
@Service
public class POIServiceImplA implements POIService{
	@Override
    public void excelUpload(){
    	System.out.println("POI A를 호출");
        
        // 내부 로직
    }
}


정상적으로 출력이 되는 모습이다

profile
코드 뇌피셜 블로그

0개의 댓글