-
스프링 핵심 원리 (2) - 스프링 컨테이너와 스프링 빈Web/Spring 2023. 8. 17. 12:14
1. 스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
- 위와 같이 스프링 컨테이너 생성, ApplicatoinContext는 인터페이스이다. (구현객체 어노테이션~,xml~등)
- 스프링 컨테이너는 XML기반 혹은 애노테이션 기반으로 만들 수 있다.
1.1 스프링 컨테이너 생성 과정
- ApplicationContext 구현객체를 생성하면, 스프링 컨테이너에 빈 저장소가 생성되고, 파라미터로 넘어온 구성 정보를 통해 스프링 빈 저장소가 채워진다.
- 빈 이름은 메서드명, 빈 객체는 리턴 값으로 채워진다.
- 빈 이름은 직접 부여할 수 있다.( @Bean(name=""))
- 스프링 컨테이너에 빈을 등록하고 난 뒤에, 스프링 컨테이너는 설정 정보를 참고해서 DI를 실행한다.
* 빈 등록시 팩토리 메서드 리턴값을 구체 타입으로 줘도 상관 없긴하다. -> 유연성 떨어지거나, 역할 구분하기 어려워짐
-> 역할과 구현 중에 역할에 의존하도록 프로그래밍 하자!! -> 팩토리 메서드에 명시된 리턴 타입으로 클라이언트가 의존할 것이다.
2. 빈 조회
2.1 모든 빈 조회
- getBeanDefinitionNames()를 통해 모든 빈 이름을 조회하고
- getBean()을 통해 빈 객체(인스턴스)를 조회한다.
- 빈 이름을 통해 BeanDefinition객체를 만들 수 있다(getBeanDefinition)
> 빈 객체에 메타 정보를 담고 있다. BeanDefinition객체에 getRole을 호출하여 Role을 확인할 수 있다.
- APPLICATION: 일반적으로 사용자가 정의한 빈
- INFRASTRUCTURE: 스프링 내부에서 사용하는 빈
2.2 이름, 타입으로 조회
- getBean("빈이름",빈타입)
- getBean("빈이름") -> Object 타입으로 리턴
- getBean(빈타입) -> 해당 타입의 빈 리턴 -> 타입 중복시 에러 발생
* 구체타입으로 조회할 수도 있다. -> 유연성 떨어짐
2.3 동일한 타입 둘 이상 조회
- getBeansOfType()을 사용하여 해당 타입의 모든 빈 조회할 수 있다.
return값은 Map<String, 빈타입>이다.
- Map을 통해 get하면 해당 타입의 모든 빈 얻을 수 있다.
2.4 빈 상속관계
- 부모 타입으로 조회하면, 자식 타입도 함께 조회된다. (타입으로만 조회시 중복 에러 가능성 있다.)
- 모든 자바 객체의 부모인 Object 타입으로 조회하면, 모든 스프링 빈을 조회한다.
3. BeanFactory와 ApplicationContext
- BeanFactory: 스프링 컨테이너 최상위 인터페이스, 빈 관리 및 조회 역할
- ApplicationContext: BeanFactory를 상속받은 인터페이스, 빈 관리 및 여러 추가 기능을 제공
-> 국제화, 환경변수, 이벤트, 리소스 조회 등
*환경변수: 로컬(내 컴퓨터 내에서 개발), 개발(테스트 서버에 올려 개발), 운영(실제 배포) 등 각각 개발 환경 단계에 맞게 구분하여 처리하는 기능
* BeanFactory를 사용할 일은 거의 없다.
4. 스프링 컨테이너 설정 정보의 다양한 형식
- 스프링 컨테이너는 다양한 형식의 설정 정보를 받도록 유연하게 설계 되어 있다
- 각 설정 정보에 맞는 구현 클래스를 사용하여 ApplicationContext 객체를 생성하면 그만이다.
* 빈을 등록하는 방법은 크게 Xml을 이용한 직접 등록(클래스 직접 생성 등록), 팩토리 메서드를 이용한 등록 (자바코드 이용)으로 나눌 수 있다.
둘 방법은 BeanDefinition을 생성시 차이가 발생
-> Xml을 사용하면, BeanClassName에 클래스명 등록됨, 팩토리 메서드는 null
-> 팩토리 메서드를 사용하면, factoryBeanName, factoryMethodName 등이 등록됨
4.1 스프링 빈 설정 메타 정보 - BeanDefinition
BeanDefinition : 빈 설정 메타정보 @Bean <bean>당 하나의 메타 정보 생성됨
스프링 컨테이너는 메타정보를 기반으로 스프링 빈을 생성함
- 이것이 가능하게 하는 중심에는 BeanDefinition이라는 추상화가 자리잡고 있다.
- XML을 읽어서 BeanDefinitoin, 자바 코드를 읽어서 BeanDefinition을 만들면 된다.
- 스프링 컨테이너는 BeanDefinition에 의존하여 Bean을 생성한다. -> 설정 내용이 자바코드인지 xml인지는 몰라도 됨
- 각 구현 객체는 ~BeanDeinitionReader 객체를 통해 설정 정보를 읽고 BeanDefinition을 생성한다.
- 새로운 형식의 설정 정보가 추가되면 ~~BeanDefinitionReader를 만들어서 BeanDefinition을 생성하면 된다.
- 따라서 설정 정보 파일(xml,자바코드) 없이도 BeanDefinition을 직접 생성하여 스프링 컨테이너에 등록할 수도 있다.
(기본 설정 후에 추가로 등록)
- BeanDefinition에는 생성할 빈의 클래스명, 팩토리빈이름(자바코드로 생성시) Scope 등 빈 정보 담고 있다.
4.2 xml을 이용한 설정
ApplicationContext ac = new GenericXmlApplicationContext("~.xml");
<beans> <bean id="memberService" class="hello.core.member.MemberServiceimpl"> <constructor-arg name="memberR" ref="memberRepository"/> </bean> <bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/> </beans> <!-- MemberRepositroy memberRepository = new MemoryMemberRepositroy(); MemberService memberService = new MemberServiceimpl(memberRepositry); 이와 같다. 즉 팩토리 메서드로 만드는 것과 큰 차이 없다.-->
- 위와 같이 빈 등록 가능하다.
- bean id: 빈이름 class:실제 빈 객체(인스턴스)
- constructor-arg는 빈 객체 생성시 생성자에 전달할 값 설정 (없으면 기본생성자)
name : 파라미터명(실제 생성자의 파라미터명과 일치해야함) ref=참조할 값 (빈 객체 중)
생성자가 여러개면 위 태그를 여러번 써야함(순서 지켜야함)
*생성자에 기본 타입이나 String 타입을 넣고싶다면, value속성을 사용한다. (단, String으로 넘어감)
<value type="long">2000 </value> -> 태그를 사용하면 타입 설정해서 넣을 수도 있다.
참고자료:
스프링 핵심 원리 (김영한)
https://conanglog.tistory.com/16
'Web > Spring' 카테고리의 다른 글
스프링 핵심 원리 (4) - 컴포넌트 스캔 (0) 2023.08.18 스프링 핵심 원리 (3) - 싱글톤 컨테이너 (0) 2023.08.17 스프링 핵심 원리 (1) - 예제 순수 자바 to 스프링 컨테이너 (0) 2023.08.16 나프 - 게시판 만들기(1) (0) 2023.08.02 Spring MVC02 - 다중파일 업로드 (0) 2023.06.30