이 때까지는 스프링을 사용하지 않고 자바 코드로만 객체지향적 설계를 공부했다.
이제는 스프링 코드로 전환해본다.
1. 스프링 컨테이너
앞에서 공부했듯이, 구성 정보를 관리하는 객체인 AppConfig.class를 DI 컨테이너 등으로 부른다고 했다. 이 DI 컨테이너를 스프링 기술을 도입한 스프링 컨테이너로 만들어보자.
@Configuration 어노테이션
클래스 위에 @Configuration 어노테이션을 붙여주었다. 이것은 해당 클래스가 설정(구성) 정보를 관리하는 클래스임을 나타낸다. org.springframework.context.annotation을 import 해야하는 것에 유의하자.
@Bean 어노테이션
각 메서드 위에 붙여줌으로써 해당 메서드의 이름을 갖는 '빈' 들을 컨테이너에 등록하게 된다. 스프링은 컨테이너에 메서드의 '빈 이름'을 key값으로, 그에 해당하는 인스턴스인 '빈 객체'를 value값으로 저장한다.
2. 스프링 컨테이너 사용해보기
AppConfig.class 컨테이너를 @Configuration과 @Bean 어노테이션을 이용해서 스프링 컨테이너로 변경해주었다. 이제 이 컨테이너를 사용해보자. 기존 CreatueApp.class 파일을 아래와 같이 바꿔준다.
변경 전에는 AppConfig 객체를 직접 불러왔는데, 변경 후에는 ApplicationContext를 불러온다.
2-1. Application Context : 스프링 컨테이너 구현체
AnnotationConfigApplicationContext는 ApplicationContext 객체를 상속받은 객체다. 실제로 ApplicationContext 객체 위에 커서를 놓은채로 [F4]를 눌러서 들어간 뒤, 그림에서 체크 표시된 버튼(또는 [Ctrl + Alt + b])으로 상속되는 객체들을 살펴보면 많은 객체들이 ApplicationContext를 상속받고 있음을 확인할 수 있다.
즉 AnnotationConfig 방식뿐 아니라, XmlConfig 방식 등, 컨테이너를 이용하는 방법이 여러가지로 많다는 것을 알아두면 된다.
이 구현체에 실제 설정 정보를 담고 있는 AppConfig.class 객체를 인자로 담아주면 스프링 컨테이너를 사용할 수 있게 된다. 이렇게 되면 AnnotationConfigApplicationContext 타입의 컨테이너를 생성하면서, AppConfig.class의 빈 객체들을 컨테이너의 빈 저장소에 등록하게 된다.
2-2. Bean 조회하기
applicationContext.getBean(Bean 이름, 객체 타입)
이제 컨테이너에 등록된 Bean들을 불러와서 구현체로 사용하면 된다. 위와 같이 작성해주면 드디어 Bean 객체를 사용할 수 있게 된다. 위에서 언급한 바와 같이, Bean 이름은 설정 정보에서의 메서드 이름과 같다.
만약 Bean 이름을 바꾸고 싶다면 @Bean(name = "바꾸고 싶은 이름") 이라고 지정하면 된다. 하지만, 바꾼 이름이 이미 존재하는 Bean과 중복되면 문제가 될 수 있으므로 이러한 상황을 만들지 않는 것이 좋다.
일부러 중복되게 만들어봤더니, 알맞지 않은 빈 객체를 호출했다는 경고를 출력한다.
-> 무조건 이런 종류의 에러가 나는 것이 아니라 상황에 따라 다른 빈을 덮어버리는 등의 에러가 발생한다고 한다.
3. 컨테이너 생성 및 DI 주입 단계 정리
컨테이너를 생성하면 스프링은 3단계 과정의 작업을 한 번에 처리한다.
- 컨테이너 생성
- 빈 등록
- 의존관계 주입
※ 더 크게 나누면 객체생성 -> 의존관계 주입 2단계로 나눌 수 있다. 그리고 생성자 주입 방식의 경우에는 이 2단계마저 한 번에 처리된다. 자세한 것은 '13. 의존관계 주입하기' 글에서 더 살펴볼 수 있다.
1. 컨테이너 생성
new AnnotationConfigApplicationContext 구문을 통해 컨테이너가 생성된다.
2. 빈 등록
AnnotationConfigApplicationContext(AppConfig.class)를 통해 설정 정보를 인자로 줘서 설정 정보의 빈들이 빈 저장소에 등록된다.
3. 의존관계 주입
그리고 정적 객체에 인자로 들어있는 동적 객체들을 연결해준다. 다시 말해서 의존 관계 주입(DI)을 처리한다. 예를 들어서 creatureService는 CreatureServiceImpl 객체를 생성하고, CreatureRepositoryAnimals()라는 객체를 동적으로 참조하는데, 이런 일련의 연결 구조를 스프링이 만들어준다.
참조
1. 인프런_스프링 핵심 원리 기본편_김영한 님 강의
www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard
'Programming-[Backend] > Spring' 카테고리의 다른 글
[TIL] 커스텀 Exception 만들기 : @ExceptionHandler, @ResponseStatus, @RestControllerAdvice, super() (0) | 2021.06.24 |
---|---|
[스프링 기초] 9. 빈 조회하기 (0) | 2021.06.15 |
[스프링 기초] 7. IoC, DI, 컨테이너 (0) | 2021.06.12 |
[스프링 기초] 6. 사용영역과 구성영역 나누기로 SRP, OCP, DIP 원칙 실현하기 (0) | 2021.06.06 |
[스프링 기초] 5. 예제만들기2 : SRP 원칙 및 객체 주입, 의존에 대한 이해 (0) | 2021.06.06 |