Written by
    
        Poogle
    
    
      
on
  on
2021.08.17 TIL
새롭게 배운 것 Done
운동
- 오전 러닝 - 2.5km
독서
알고리즘
코딩
IoC(Inversion of Control) - 제어의 역전
- 일반적인 제어권: 내가 사용할 의존성은 내가 만들기
class VoucherController {
  private VoucherRepository repository = new VoucherRepository();
}
- IoC: 내가 사용할 의존성을 다른 누군가 알아서 주도록 하기
class VoucherController {
  private VoucherRepository repository;
  
  public VoucherController(VoucherRepository repository) {
    this.repository = repository;
  }
  ///
}
class VoucherControllerTest {
  @Test
  public void create() {
    VoucherRepository repository = new VoucherRepository();
    VoucherController voucherController = new VoucherController(repository)
  }
}
Spring IoC Container

- 빈(Bean) 객체의 생성, 초기화, 보관, 제거 등을 관리하고 있음 => 컨테이너
- 스프링의 핵심 기능: 객체를 생성하고 초기화하는 것
    - -> Application Context라는 인터페이스에 정의
- -> AnnotationConfigApplicationContext: 이 인터페이스를 알맞게 구현한 클래스 중 하나, 자바 클래스에서 정보를 읽어와 객체 생성과 초기화를 수행
 
- 싱글톤 객체
    - 별도의 설정을 하지 않을 경우 스프링은 한 개의 빈 객체만을 생성
- 이 때 빈 객체는 싱글톤(단일 객체) 범위를 갖는다고 표현
- 스프링은 기본적으로 한 개의 @Bean어노테이션에 대해 한 개의 빈 객체를 생성
 
Bean이란?
- 스프링 IoC 컨테이너가 관리하는 객체
    - @Bean어노테이션을 메서드에 붙이면 해당 메서드가 생성한 객체를 스프링이 관리하는 객체로 등록
 
- 오로지 Bean들만 의존성 주입을 해줄 수 있음
- 등록하려면?
    - Component Scan: 어디서부터 찾을 것인지 알려줌
        - @Component
- @Repository
- @Service
- @Controller
- @Configuration
 
- XML이나 자바 설정 파일에 일일히 등록(@Bean으로)
 
- Component Scan: 어디서부터 찾을 것인지 알려줌
        
- 꺼내쓰려면?
    - @Autowired또는- @Injection
- getBean()
 
의존성 주입(Dependecy Injection)
- 의존: 변경에 의해 영향을 받는 관계
    - 어떤 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 의존한다고 표현
- 의존하는 대상이 있으면 그 대상을 구하는 방법이 필요 -> 가장 쉬운 방법: 의존 대상 객체를 직접 생성
 public class MemberRegisterService { //의존 객체를 직접 생성 private MemberDao memberDao = new MemberDao(); } //의존하는 MemberDao의 객체도 함께 생성 MemberRegisterService service = new MemberRegisterService();- 클래스 내부에서 직접 의존 객체를 생성하는 것이 쉽긴 하지만 유지보수 관점에서 문제점을 유발할 수 있음
 
- 어떤 한 클래스가 다른 클래스의 메서드를 실행할 때 이를 
- DI를 통한 의존 처리
    - 의존하는 객체를 직접 생성하는 대신 의존 객체를 전달받는 방식을 사용
 
public class MemberRegisterService {
  private MemberDao memberDao;
  
  public MemberRegisterService(MemberDao memberDao) {
    this.memberDao = memberDao;
  }
}
//의존객체를 생성자를 통해 주입
MemberDao dao = new MemberDao();
MemberRegisterService service = new MemberRegisterService(dao);
- 의존 객체를 직접 생성 X -> 생성자를 통해 MemberRegisterService가 의존하고 있는 MemberDao 객체를 주입 받음
- 왜? 이렇게 복잡하게 하는가?
    - 변경의 유연함
 
@Autowired / @Injection를 어디에 붙일까? - DI 방식
- 생성자 - 가장 권장
    - 빈 객체를 생성하는 시점에 모든 의존 객체가 주입됨
- 필수적으로 필요한 객체 만들수 있도록 강제하기 위해
- 테스트 쉽게 (mock)
- 불변성 확보 -> 불변객체 -> thread safety
 
public class MemberRegisterService {
  private final MemberDao memberDao;
  
  public MemberRegisterService(MemberDao memberDao) {
    this.memberDao = memberDao;
  }
}
- 필드
@Autowired
private MemberDao memberDao;
- setter
    - 세터 메서드 이름을 통해 어떤 의존 객체가 주입되는지 알 수 있음
- 필요한 의존 객체를 전달하지 않아도 빈 객체가 생성되기 때문에 객체를 사용하는 시점에 NullPointerException이 발생할 수 있음
 
public class MemberRegisterService {
  private MemberDao memberDao;
  
  @Autowired
  public void setMemberRegisterService(MemberDao memberDao) {
    this.memberDao = memberDao;
  }
}
참고: 책 - 스프링5 프로그래밍 입문 - 최범균 강의 - 예제로 배우는 스프링 입문 - 백기선
깨달은 점 FEELING
- 면접 질문으로 자주 등장한다고 하는 내용이라 정리를 제대로 해놔야겠다는 생각이 들었다.