1️⃣ 개요
전에 스프링 컨테이너와 관련된 글을 올렸지만, 좀 더 깔끔하고 간결하게 중요한 내용만 다시 작성하였다.
따라서 아래 글을 읽고 온다면 조금 더 이해하기 쉬울 것이다.
https://jnsodevelop.tistory.com/35
[Spring] Spring Container (스프링 컨테이너) - (1)
Spring Container (스프링 컨테이너) Spring 에서 'ApplicationContext' 는 '스프링 컨테이너' 라고 한다. 이는 DI, IoC 와도 관련이 있는데, 스프링 컨테이너를 통해 DI가 자동으로 되기 때문이다. 스프링 컨테이
jnsodevelop.tistory.com
다시 김영한님의 강의를 들으며 Java 와 Spring을 깊게 공부해보려고 한다.
2️⃣ 스프링 컨테이너?
1. 구성
객체지향 프로그래밍을 할 때 SOLID 원칙을 지키는 것은 좋은 코드를 작성하는데에 큰 도움을 준다.
그 중 DIP, IOC 등과 관련된 스프링 컨테이너는 서로 다른 Bean을 연결함으로써 애플리케이션의 전반적인 흐름, 의존 관계 등을 관리해준다. 즉, 스프링 컨테이너는 자동으로 자바 객체들을 관리해주는 역할을 하여 생명 주기를 관리해준다.
스프링 컨테이너를 생성하는 방법엔 여러 방법이 있다.
XML을 기반으로 만들 수도 있고, Annotation 기반의 Java 설정 클래스로도 만들 수 있다.
만약 Java 설정 기반의 스프링 컨테이너를 만든다면, 다음과 같은 기본 코드가 필요하다.
ApplicationContext ac = new AnnotationConfigApplicationContext(설정정보.class);
여기서 ApplicationContext 는 스프링 컨테이너를 말하며, 인터페이스이다.
다음으로 new 연산자를 통해 생성된 AnnotationConfigApplicationContext 는 그 구현체이다.
글자 수가 많아 외우기 힘들진 모르겠지만, IntelliJ와 같은 IDE를 사용한다면 쉽게 작성할 수 있을 것이다.
괄호 안의 설정정보.class 는 실제로 설정 정보를 담고 있는 클래스를 의미한다.
예를 들어 다음과 같을 수 있다.
@Configuration
public class AppConfig{
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository);
}
@Bean
public MemberRepository memberRepository(){
return new JDBCRespository();
}
}
위 경우엔 설정정보 자리에 AppConfig.class 가 들어가는 것이다.
2. 생성 과정
1. 스프링 컨테이너 생성
스프링 컨테이너가 만들어지기 위해선 설정 정보(구성 정보)를 담은 클래스가 있어야 한다.
위의 AppConfig.class 가 그 역할을 하는 것이다.
다음으로 스프링 컨테이너 내에 스프링 빈 저장소(Spring Bean Repository)가 생성된다.
이는 빈 이름과 빈 객체의 정보를 담고 있다.
예를 들어 저장소는 다음과 같은 구조를 가진다.
Bean Name | Bean Object |
2. 스프링 빈 등록
스프링 컨테이너는 파라미터를 통해 넘어온 정보를 바탕으로 스프링 빈을 등록한다.
Bean Name | Bean Object |
memberService | MemberServiceImpl@x01 |
memberRespository | JDBCRepository@x02 |
여기서 알 수 있는 사실을 다음과 같다.
- 구성 정보를 바탕으로 @Bean 어노테이션으로 등록한 빈이 저장된다.
- 메소드 이름이 곧 빈 이름이 된다. 하지만 직접 부여를 하는 것도 가능한다. -> @Bean(name="이름")
- 스프링 빈은 중복된 이름이 있으면 안된다. 기존 빈이 무시되거나 덮어버리는 등의 오류가 발생할 수 있다.
3. 의존 관계 설정
스프링 컨테이너는 설정 정보를 참고하여 의존관계를 주입한다. (여기서 DI의 개념이 사용된다.)
위 예시에선 MemberServiceImpl 의 파라미터로 memberRespository() 가 적용되었다.
즉, memberRepository 메소드의 반환값인 JDBCRepository가 파라미터로 들어간다는 뜻이다.
이렇듯 외부에서 의존관계를 설정해준다면, 실제 구현체에서 어떻게 처리될까?
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
...
}
위 방법은 의존성 주입을 받는 여러 방법 중 '생성자 주입'의 방법이다.
보이는 것 처럼 해당 클래스는 인터페이스에만 의존하여 DIP를 만족할 수 있게 된다.
실제로 빈을 등록할 때 생성자를 호출하면서 의존관계 주입도 함께 처리된다.
참고 : 김영한-스프링 핵심 원리 (기본편), google