책읽기

[스프링5 프로그래밍 입문][chap03] 스프링 DI

pythaac 2022. 3. 4. 22:01

https://github.com/pythaac/Spring_tutorial/tree/main/%EC%8A%A4%ED%94%84%EB%A7%815%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EC%9E%85%EB%AC%B8/chap03/src/main/java/com/example/chap03

 

GitHub - pythaac/Spring_tutorial: These are test tutorial codes between react native(android) and spring boot

These are test tutorial codes between react native(android) and spring boot - GitHub - pythaac/Spring_tutorial: These are test tutorial codes between react native(android) and spring boot

github.com

 

1. 의존(Dependency)이란?

  • 의존 정의
    • 객체 간의 의존을 의미
    • 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 '의존'한다라고 표현
    • 의존은 변경에 의해 영향을 받는 관계
  • 의존 객체를 가져오는 방법
    • 객체를 직접 생성 -> 그러나 유지보수 관점에서 문제를 유발할 수 있음
    • 1) DI
    • 2) 서비스 로케이터

 

2. DI(Dependency Injection)를 통한 의존 처리

  • DI 정의
    • 의존 객체를 직접 생성하지 않고 전달받는 방식
  • 의존 객체를 굳이 주입하는 이유?

 

3. DI와 의존 객체 변경의 유연함

  • 의존 객체를 직접 생성하는 방식
    • new 연산자를 이용해서 객체를 생성
    • 사용하는 객체가 변경될 때, new 연산자를 사용한 모든 line을 수정해야함
  • DI를 사용하는 방식
    • 어셈블러에서 생성하는 객체만 변경

 

4. 예제 프로젝트 만들기

  • 위 github에 작성

 

5. 객체 조립기

  • 조립기(assembler)
    • 객체를 생성하고 의존 객체를 주입하는 클래스
    • 조립기 클래스의 get 메서드를 이용해서 필요햔 객체를 구하고 사용
  • 참고
    • 특정 클래스의 메서드를 표시할 때 '#' 사용
    • BufferedReader#readLine()

 

6. 스프링의 DI 설정

  • 스프링의 DI
    • 스프링은 DI를 지원하는 조립기
    • 어셈블러는 특정 타입 클래스만 생성하지만, 스프링은 범용 조립기
  • 설정 정보
    • 스프링을 사용하려면 다음을 정의한 설정정보를 작성해야함
      1) 어떤 객체를 생성하고
      2) 의존을 어떻게 주입할지
    • @Configuration
      스프링 설정 클래스
    • @Bean
      해당 메서드가 생성한 객체를 스프링 빈으로 설정
  • 스프링 컨테이너
    • 의존 객체를 주입하는 것은 스프링 컨테이너
    • 설정 클래스를 이용해 컨테이너를 생성해야함
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);

// 컨테이너에서 이름이 memberRegSvc인 빈 객체를 구함
// 빈 이름은 메서드 이름
MemberRegisterService regSvc =
		ctx.getBean("memberRegSvc", MemberRegisterService.class);
  • DI 방식 1 : 생성자 방식
    • 생성자를 통해 의존 객체를 주입받아 필드에 할당
    • (참고)
      return 타입이 Collection<Member> -> 상위 클래스를 사용
  • DI 방식 2 : 세터 메서드 방식
    • 세터 메서드를 이용해서 객체를 주입
  • 생성자 vs 세터 메서드
    • 생성자 방식
      • 장점
        빈 객체를 생성하는 시접에 모든 의존 객체 주입이 완료
      • 단점
        주입 받는 객체의 어떤 member로 주입되는지 명확하지 않음
    • 세터 방식
      • 장점
        세터 메서드 이름을 통해 어떤 member에 주입되는지 명확
      • 단점
        set되지 않은 member가 있어도 생성될 수 있음 (NullPointerException)

 

7. @Configuration 설정 클래스의 @Bean 설정과 싱글톤

  • 아래와 같은 설정 클래스는 매번 새로운 객체를 생성?
@Configuration
public class AppCtx{
    @Bean
    public MemberDao memberDao() {
    	return new MemberDao();
    }
}
  • 스프링 컨테이너는 @Bean이 붙은 메서드에 대해 한 개의 객체만 생성
    • memberDao()를 몇 번을 호출해도 항상 같은 객체를 리턴
    • 스프링은 설정 클래스를 상속한 새로운 설정클래스를 만들어서 사용
    • 이 때 생성되어 있는지 확인

 

8. 두 개 이상의 설정 파일 사용하기

  • @Autowired
    • 스프링의 자동 주입 기능을 위한 것
    • 설정 클래스에서 사용한 @Autowired에 대해서도 자동 주입
    • 설정 클래스를 내부적으로 스프링 빈으로 등록
  • @Import
    • 설정 파일에서 설정 파일을 가져옴
    • 두 개 이상의 설정 클래스를 지정 가능
    • AppConfImport를 설정파일로 등록시, AppConf1과 AppConf2 모두 등록
@Configuration
@Import( {AppConf1.class, AppConf2.class} )
public class AppConfImport {}

 

9. getBean() 메서드 사용

  • getBean()
    • getBean(이름, 타입) => 이름은 메서드 이름
    • VersionPrinter = versionPrinter = ctx.getBean("versionPrinter", VersionPrinter.class);
  •  Exception
    • NoSuchBeanDefinitionException : 빈 이름이 없을 때, 타입으로만 찾는데 이름이 없을 때
    • BeanNotOfRequiredTypeException : 빈 타입이 다를 때
    • NoUniqueBeanDefinitionException : 타입으로만 구하는데 이름이 2개 이상일 때

 

10. 주입 대상 객체를 모두 빈 객체로 설정해야 하나?

  • 스프링 빈 등록 차이
    • 스프링 컨테이너가 객체를 관리하는지 여부
    • 등록하지 않으면 스프링 컨테이너에서 객체를 구할 수 없음