• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

DI 적용해보기

24.04.28 02:40 작성 24.04.28 03:24 수정 조회수 110

0

 안녕하세요! 유익한 수업 너무 재밌게 잘 듣고 있습니다. 감사합니다.
제가 많이 미흡하여 이상한 질문일 수 있는 점 미리 양해부탁드립니다.

강사님께서 FrontControllerServletV5 의 handlerMappingMap, handlerAdpaterList 에 DI 를 할 수 있다는 말씀을 듣고 공부차원에서 시도해보았는데요.

아래와 같이 handlerMappingMap, handlerAdpaterList 를 일급 컬렉션으로 만들어 HandlerMappingConfig 와 HandlerAdapterConfig 를 이용하여 @Bean 으로 등록했습니다. FrontControllerServletV5 에는 @RequiredArgsConstructor 를 이용해 의존관계를 주입했습니다.

FrontControllerServletV5

@RequiredArgsConstructor
@WebServlet(name = "frontControllerServletV5", urlPatterns = "/front-controller/v5/*")
public class FrontControllerServletV5 extends HttpServlet {

    private final HandlerMappingMap handlerMappingMap;
    private final HandlerAdapterList handlerAdapterList;

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

       ...
    }

    private Object getHandler(HttpServletRequest request) {
        return handlerMappingMap.getHandler(request);
    }

    private MyHandlerAdapter getHandlerAdapter(Object handler) {
        return handlerAdapterList.getHandlerAdapter(handler);
    }

   ...
}

 

 HandlerAdapterConfig

@Configuration
public class HandlerAdapterConfig {

    @Bean
    public HandlerAdapterList handlerAdapterList() {
        return new HandlerAdapterList(registerHandlerAdapters());
    }

    private List<MyHandlerAdapter> registerHandlerAdapters() {
        List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
        handlerAdapters.add(new ControllerV3HandlerAdapter());
        handlerAdapters.add(new ControllerV4HandlerAdapter());
        handlerAdapters.add(new ControllerV2HandlerAdapter());
        return handlerAdapters;
    }
}



HandlerMappingConfig

@Configuration
public class HandlerMappingConfig {
    @Bean
    public HandlerMappingMap handlerMappingMap() {
        return new HandlerMappingMap(registerHandlers());
    }

    private Map<String, Object> registerHandlers() {
        HashMap<String, Object> urlMap = new HashMap<>();
        urlMap.put("/front-controller/v5/v2/members/new-form", new MemberFormControllerV2());
        urlMap.put("/front-controller/v5/v2/members/save", new MemberSaveControllerV2());
        urlMap.put("/front-controller/v5/v2/members", new MemberListControllerV2());

        urlMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
        urlMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
        urlMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());

        urlMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
        urlMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
        urlMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
        return urlMap;
    }
}


HandlerAdapterList

public class HandlerAdapterList {
    private final List<MyHandlerAdapter> handlerAdapters;

    public HandlerAdapterList(List<MyHandlerAdapter> handlerAdapters) {
        this.handlerAdapters = handlerAdapters;
    }

    public MyHandlerAdapter getHandlerAdapter(Object handler) {
        for (MyHandlerAdapter handlerAdapter : handlerAdapters) {
            if (handlerAdapter.supports(handler)) {
                return handlerAdapter;
            }
        }
        throw new IllegalArgumentException("handler adapter 를 찾을 수 없습니다. handler=" + handler);
    }
}


HandlerMappingMap

public class HandlerMappingMap {

    private final Map<String, Object> handlerMappingMap;

    public HandlerMappingMap(Map<String, Object> handlerMappingMap) {
        this.handlerMappingMap = handlerMappingMap;
    }

    public Object getHandler(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        return handlerMappingMap.get(requestURI);
    }
}


정상 작동하는 것은 확인하였지만, 몇가지 궁금한 사항이 있어서 질문 드립니다.
1. @Configuration 과 @Bean, 일급 컬렉션을 이용한 방법 말고도 다른 DI 적용 방법이 있을까요?

2. Map, List 를 일급 컬렉션으로 만드는 과정에서 getHandlerAdapter, getHandler 와 같은 메서드들을 의미있는 논리 메서드로 판단해서 각각의 컬렉션의 메서드로 뺐는데, 제가 맞게 판단한 것일까요?

3. 여전히 registerHandlers, registerHandlerAdapters 에는 각각의 객체들을 더하는 코드들이 길게 나열되어 있어 지저분합니다. 이것들도 깔끔하게 자동으로 주입 받는 방법이 있을까요? (강사님께서 언급하신 @RequestMapping 어노테이션의 작동 원리와 관련이 있을까요? spring-webmvc 코드를 살펴보았을 때는 SimpleUrlHandlerMapping 의 protected void registerHandlers(Map<String, Object> urlMap) 을 통해 url 을 등록하는 것으로 보이는데, 이것과 연관이 있을까요?)

긴 글 읽어주셔서 감사합니다.

답변 2

·

답변을 작성해보세요.

1

안녕하세요. rjf1138님

전체적으로 보았을 때 잘 구현하셨습니다 🙂

지금 정도면 더 개선하지 않아도 될 정도로 충분히 잘 구현한 코드라 생각합니다.

그리고 지금과 같은 코드 개선 질문의 경우 강의 학습 내용이 주가 아니어서 저도 참 어렵고 죄송하지만 질문 안내에서 말씀드린 것처럼 강의 학습에 관련된 질문을 올려주시길 부탁드립니다.

저도 마음으로는 도움을 드리고 싶지만, 하루에도 수많은 분들이 질문을 올려주십니다. 그래서 강의 학습과 관련된 질문에 초점을 맞추는 것이 맞다 생각합니다. 다시한번 이해를 부탁드립니다.

0

rjf1138님의 프로필

rjf1138

질문자

2024.04.30

넵 바쁘신데 답해주셔서 감사합니다. 강의 내용과 이어지는 코드 개선이어서 질문 글 작성을 해도 되는 줄 착각했습니다. 다음에는 강의 학습과 관련된 질문을 올리도록 하겠습니다.
항상 좋은 강의해주셔서 많이 배우고 있습니다. 감사합니다.