delpho

Spring에 대하여 - 2 본문

CS

Spring에 대하여 - 2

delpho 2022. 6. 3. 02:16

1. DI 종류는 어떤것이 있고, 이들의 차이는 무엇인가요?

 

IoC의 종류와 유형

 

위의 그림에서는 DI의 종류가 저렇게 3가지로 되어있다.

 

근데.. 조금 찾아보니 분류가 조금 다르게 되있는거같아서 찾아본 내용으로 다시 정리를 해보려한다.

 

DI (Dependency Injection)의 종류는 크게 3개가 있다.

 

 

 

1. 생성자 주입 방식 (Constructor Injection)

  • 말 그대로 생성자를 통해 의존성 주입 (DI)
  • 가장 권장되는 주입 방식
  • Lombok 사용하면 간단하게 사용 가능 (@AllArgsConstructor)
  • 객체의 불변성 확보 (final 사용 가능)
  • 의존 관계를 주입하지 않으면 Controller 객체 생성 불가
  • 순환 의존성 파악 가능
    • Bean 객체를 생성하는 시점에 생성자의 파라미터 빈 객체를 찾아 먼저 주입한 뒤, 주입 받은 Bean 객체를 이용하여 생성 (주입 후 생성)
      • --> 런타임 시점이 아닌, 구동 시점에 순환 의존성 (순환 참조 발견 가능)
@Service
public class BoardService {

    private BoardDao boardDao;

    // @Autowired Spring 4.3 버젼 부터 @Autowired 생략가능 (생성자가 1개만 있을 경우)
    public BoardService(BoardDao boardDao) {
        this.boardDao = boardDao;
    }
}

 

 

 

2. 필드 주입 방식 (Field Injection)

  • @AutoWired 어노테이션을 통해 의존성 주입
  • 주의!!!
    • 참조 관계를 한눈에 파악하기 어려움
    • final을 선언할 수 없어서 객체가 변할 수 있음
    • Bean 객체를 먼저 생성한 뒤에 의존성 주입 (생성 후 주입)
class Controller {

   @Autowired
   private Service service;
}

 

 

 

3. 수정자 주입 방식 (Setter Injection, method Injection에 포함(?))

  • Setter(setXXX)를 통해 의존성 주입
  • Spring 3.x 버전에서까지 권장된 방식
@Component
public class SampleController {
    private SampleService sampleService;
 
    @Autowired
    public void setSampleService(SampleService sampleService) {
        this.sampleService = sampleService;
    }
}
  • 주의!!
    • 이 방식을 사용했을때, Service의 구현체를 주입하지 않아도 Controller 객체 생성이 가능함
      • --> Service의 함수를 사용하다보니, NPE 발생할 수 있음
      • 이를 해결할 수 있는 방법 --> 생성자 주입

 

 

# 순환 참조란?

  • 서로가 서로의 객체를 참조
    • 서로의 객체를 참조하며 메소드를 실행하면 무한 루프가 되어 Stack이 쌓이다가 터져버림
@Component
public class Chicken {
    @Autowired
    Egg egg;

    public void layEgg(){
        egg.becomeChicken();
    }

}

@Component
public class Egg {
    @Autowired
    Chicken chicken;

    public void becomeChicken() {
        chicken.layEgg();
    }

}

@Bean
public CommandLineRunner run(Chicken chicken, Egg egg) throws Exception {
    return (String[] args) -> {
        chicken.layEgg(); // 실행
    };
}

 

 

 

 

2. Autowiring 과정에 대해서 설명해주세요.

컨테이너가 타입(인터페이스 또는 객체)를 이용해 의존 대상 객체를 검색하고 할당할 수 있는 Bean 객체를 찾아 주입

 

Bean 생성 주기 도식화

 

  • BeanPostProcessor
    • 인터페이스 
    • Bean의 초기화 라이프 사이클 이전 이후에 필요한 부가 작업을 할 수 있는 라이프 사이클 콜백
    • IoC 컨테이너에 등록되어 있음

postProcessBeforeInitialization가 Bean을 찾아줌

 

  • AutowiredAnnotationBeanPostProcessor
    • BeanPostProcessor의 구현체
    • BeanPostProcessor의 구현체이므로 IoC 컨테이너에 Bean으로 등록되어있음
    • @AutoWired에 있어서 핵심이 되는 클래스
    • Bean의 초기화 라이프 사이클 이전 (생성 전)에 @AutoWired가 붙어있는 Bean을 찾아 주입해주는 작업을 함
    • @Autowired가 적용된 필드, 생성자, 메서드에 알맞은 의존 객체를 주입해주는 기능을 제공

AutowiredAnnotationBeanPostProcessor의 메서드

  • (@Autowired로 어노테이티드된 필드나 메서드에 대해서 객체를 주입하는 역할을 수행)
  • InjectionMetaData 클래스의 inject 메서드를 호출하여 객체를 주입

InjectionMetaData 클래스의 inject 메서드

  • 이 메서드가 객체를 주입할 때, ReflectionUtils 클래스를 사용
    • @Autowired는 리플렉션을 통해 수행
      • @Autowired되는 객체들은 일반적으로 private으로 선언되는 경우가 많음
      • 그럼에도 객체가 주입될 수 있는 것은 리플렉션 때문
      • 위 코드상에서는 makeAccessible 메서드가 이를 가능하게 함!
      • 리플렉션은 따로 공부하기..!

 

 

 

 

동작 순서 정리!

  1. beans.xml (또는 java configuration)을 로딩하여 Final Bean Definition 생성 (Bean에 대한 설정 정보, 바탕으로 Bean 생성)
  2. IoC 컨테이너의 최상단에 있는 BeanFactory( ApplicationContext )가 BeanPostProcessor 타입의 Bean을 찾는다.(AutowiredAnnotationBeanPostProcessor)
  3. IoC 컨테이너에 등록되어있는 다른 일반적인 Bean (@AutoWired로 의존성 주입이 필요한 bean) 에게  AutowiredAnnotationBeanPostProcessor의 로직이 적용된다. (processInjection 메서드)
  4. 의존성 주입이 일어난다.

 

 

 

추가로..

 

@Autowired 애노테이션의 적용 순서 (실제 의존 객체를 찾는 순서)


1) 타입이 같은 빈 객체를 검색한다. 한 개면 그 빈 객체를 사용한다.
    @Qualifier가 명시되어 있을 경우, @Qualifier와 같은 값을 갖는 빈 객체여야한다.

2) 타입이 같은 빈 객체가 두 개 이상 존재하면, @Qualifier로 지정한 빈 객체를 찾는다.
    존재하면, 그 객체를 사용한다.

3) 타입이 같은 빈 객체가 두 개 이상 존재하고 @Qualifier가 없을 경우, 이름이 같은 빈 객체를 찾는다.
    존재하면, 그 객체를 사용한다.
   (@Autowired가 적용된 필드나 설정 메서드의 프로퍼티 이름과 같은 이름을 가진 빈 객체)

위 경우에 해당되지 않으면 스프링 컨테이너는 익셉션을 발생시킨다.

 

 

 

3. Spring Web MVC의 Dispatcher Servlet의 동작 원리에 대해서 간단히 설명해주세요.

 

Dispatcher Servlet 동작 원리

 

  1. ~~~~/login 으로 요청이 들어옴 (웹브라우저 요청)
  2. DS는 이 URI를 가지고 HM에게 나 뭐해야돼? 라고 물어봄
    • 굳이 따지면 if elseif 부분을 HM이 해줌 (Spring httpServlet 부분)
  3. HM이 “야 xxxController가 xx()있는데 거기로 가면 돼” 하면서 처리 controller 리턴
  4. 해당 컨트롤러의 해당 메소드로 요청
  5. 4.5. 데이터 받고 + 서비스 call + dao + 응답페이지 리턴 하기
  6. ModelAndView 응답 받음 (view 는 list 이름만 받음)
  7. VR에게 “야 컨트롤러가 나한테 list라고 줬는데 이게 뭔말이야”
  8. VR은 앞에 경로 + 뒤에 .jsp 붙여줌 (/view/user/list.jsp)

 

 

4. 프론트 컨트롤러 패턴이란 무엇인가요?

 

 

기존의 패턴을 설명하자면

 

 

클라이언트들은 Controller A, B, C를 각각 호출하는 형태이다.

여기서 프론트 컨트롤러 패턴을 도입하게 되면?

 

 

클라이언트들의 요청을 Front Controller가 받고,

Front Controller는 각 요청에 알맞는 Controller를 찾아서 호출시킨다.

공통 코드는 FC가 처리한다. (Spring에서는 Dispatcher Servlet이 담당)

 

 

 

 

 

 

 

 

 

참고

https://velog.io/@walker/Spring-%EC%99%9C-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%A3%BC%EC%9E%85%EC%9D%B4-%EA%B6%8C%EC%9E%A5%EB%90%98%EB%A9%B0-%EC%88%9C%ED%99%98%EC%B0%B8%EC%A1%B0%EB%9E%80-%EB%AD%98%EA%B9%8C

 

생성자 주입은 왜 권장되며 순환참조란 뭘까?

면접에서 수정자 주입과 생성자 주입 중 어느 것이 바람직한가에 대해 질문 받은 적이 있다그때 생성자 주입이 권장된다는 사실은 기억났지만 정확한 이유를 설명하지 못했다.그때의 아쉬움이

velog.io

https://soobarkbar.tistory.com/230

 

스프링 의존성 주입 방식 종류와 차이

의존성 주입 (Dependency Injection) 의 종류 1. 생성자 주입 방식 (Constructor Injection) 생성자를 통해 의존성을 주입하는 방식이다. 총 3가지 주입 방식 중 가장 권장되는 주입 방식이다. (아래에서 자세히

soobarkbar.tistory.com

https://mangkyu.tistory.com/125

 

[Spring] 다양한 의존성 주입 방법과 생성자 주입을 사용해야 하는 이유 - (2/2)

Spring 프레임워크의 핵심 기술 중 하나가 바로 DI(Dependency Injection, 의존성 주입)이다. Spring 프레임워크와 같은 DI 프레임워크를 이용하면 다양한 의존성 주입을 이용하는 방법이 ..

mangkyu.tistory.com

https://beststar-1.tistory.com/40

 

@Autowired의 동작원리

@Autowired란? 의존관계 주입(DI)을 할 때 사용하는 어노테이션(Annotation)이며, 의존 객체의 타입에 해당하는 빈(Bean)을 찾아 주입하는 역할을 한다. 💡 의존관계 주입에 대해서는 IoC(Inversion of Control,

beststar-1.tistory.com

https://jjingho.tistory.com/6

 

[스프링 핵심기술] - @Autowired

백기선님의 스프링 프레임워크 핵심 기술이라는 강좌를 들으며 공부한 내용을 정리한 글입니다. 오늘은 @Autowired Annotation의 사용 방법, 동작 원리까지 알아본다. 1. @Autowired란? @Autowired는 의존성

jjingho.tistory.com

https://kellis.tistory.com/58

 

@Autowired는 어떻게 동작하는 걸까?

@Autowired는 Spring Framework에서 Dependency Injection을 위해 제공하는 어노테이션으로, 이를 모르는 웹 개발자는 없을 것입니다. 우리는 습관처럼 자연스럽게 @Autowired를 사용하여 객체를 주입받습니다.

kellis.tistory.com

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=javaking75&logNo=220728817382 

 

[스프링] 의존 자동 주입 > @Autowired 애노테이션과 의존 객체를 찾는 순서

@Autowired 애노테이션을 이용한 의존 자동 주입자동 주입 기능을 사용하면 스프링이 알아서 의존 객체를 ...

blog.naver.com

https://yeonyeon.tistory.com/103

 

[MVC] 프론트 컨트롤러 패턴

기존의 패턴을 설명하자면 아래 그림과 같다 각 클라이언트들은 Controller A, B, C에 대해 각각 호출한다. 공통 코드들은 별도로 처리되어 있지 않고 각 Controller에 포함되어 있다. 하지만 프론트 컨

yeonyeon.tistory.com

 

'CS' 카테고리의 다른 글

Java에 대하여 - 3  (0) 2022.06.10
Java에 대하여 - 2  (0) 2022.06.08
Java에 대하여 - 1  (0) 2022.06.08
Spring에 대하여 - 3  (0) 2022.06.04
Spring에 대하여 - 1  (0) 2022.06.02