728x90
4.스프링 컨테이너와 스프링 빈
- 목차
- 1.스프링 컨테이너 생성
- 2.컨테이너에 등록된 모든 빈 조회
- 3.스프링빈 조회(기본)
- 4.스프링빈 조회(동일한 타입이 둘이상)
- 5.스프링빈 조회(상속관계)
- 6.BeanFactory 와 ApplicationContext
- 7.다양한 설정 형식 지원 - 자바코드 , XML
- 8.스프링 빈 설정 메타정보 - BeanDefinition
1.스프링 컨테이너 생성
스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
- ApplicationContext - 스프링 컨테이너 , 인터페이스
- AnnotationConfigApplicationContext - 애노테이션 기반의 자바 클래스로 만드는것
- XML 기반으로 만들수 있다
- AppConfig - 애노테이션 기반의 자반 설정 클래스로 만든것
- AnnotationConfigApplicationContext 는 ApplicationContext 의 구현체이다!
2.컨테이너에 등록된 모든 빈 조회
모든 빈 출력하기
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean(){
String[] beanDefinitionNames= ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean= ac.getBean(beanDefinitionName);
System.out.println("Name = " + beanDefinitionName + "Object" + bean);
}
}
}
애플리케이션 빈 출력하기
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean(){
String[] beanDefinitionNames= ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
//내가등록한 애플리케이션 빈
if(beanDefinition.getRole()==BeanDefinition.ROLE_APPLICATION){
Object bean= ac.getBean(beanDefinitionName);
System.out.println("Name = " + beanDefinitionName + "Object" + bean);
}
}
}
}
- BeanDefinition.ROLE_APPLICATION 을 이용해서 내가등록한 애플리케이션 빈을 출력한다
3.스프링빈 조회(기본)
빈 이름 조회
public class ApplicationContextBasicInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 이름 조회")
void findBeanByName(){
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
- memberService 의 isInstanceOf 가 MemberServiceImpl 을 가리키면 성공!
이름 없이 타입으로 조회
public class ApplicationContextBasicInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("이름 없이 타입으로 조회")
void findBeanByType(){
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
- "memberService" 없이 타입으로 조회 가능
구체 타입으로 조회
public class ApplicationContextBasicInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("구체 타입으로 조회")
void findBeanByName2(){
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
- MemberServiceImpl 구체클래스로 조회가 가능하다
구체 타입으로 조회
public class ApplicationContextBasicInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("구체 타입으로 조회")
void findBeanByName2(){
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
- MemberServiceImpl 구체클래스로 조회가 가능하다
빈 이름으로 조회X
public class ApplicationContextBasicInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 이름으로 조회X")
void findBeanByNameX(){
assertThrows(NoSuchBeanDefinitionException.class,
() -> ac.getBean("xxxx", MemberServiceImpl.class));
}
}
- NoSuchBeanDefinitionException 예외가 터진다
4.스프링빈 조회(동일한 타입이 둘이상)
타입으로 조회시 같은 타입이 둘 이상 있으면 , 중복 오류가 발생
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면 , 중복 오류가 발생")
void findBeanByTypeDuplication(){
Assertions.assertThrows(NoUniqueBeanDefinitionException.class,
()->ac.getBean(MemberRepository.class));
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
}
- SameBeanConfig 을 static 으로 만들면서 해당 클래스에만 쓴다고 만든다
- NoUniqueBeanDefinitionException 같은타입이 2개가 있을때 발생하는 오류
타입으로 조회시 같은 타입이 둘 이상 있으면 , 빈 이름으로 지정한다
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면 , 빈 이름으로 지정한다")
void findBeanByName(){
MemberRepository memberRepository=ac.getBean("memberRepository1",MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
}
- 같은 타입이 있을 경우 빈이름으로 조회
특정 타입 모두 조회
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("특정 타입 모두 조회")
void findBeanByType(){
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
for (String s : beansOfType.keySet()) {
System.out.println("s = " + s + " value =" + beansOfType.get(s));
}
System.out.println("beansOfType = " + beansOfType);
assertThat(beansOfType.size()).isEqualTo(2);
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
}
- getBeansOfType 을 이용하면 Map 에 key,value 로 등록된다
- beansOfType 을 호출하면서 모두 조회된것을 알수 있다
5.스프링빈 조회(상속관계)
- 부모타입으로 조회하면 자식타입도 함께 조회된다
- 자바의 최상위 부모는 Object 를 조회하면 모든스프링 빈 조회
부모타입 Object
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac =new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("부모타입 Object")
void findAllBeanByObjectType(){
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value" + beansOfType.get(key));
}
}
@Configuration
static class TestConfig{
@Bean
public DiscountPolicy rateDiscountPolicy(){
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy(){
return new FixDiscountPolicy();
}
}
}
- object 조회시 스프링의 모든 빈이 조회된다
6.BeanFactory 와 ApplicationContext
- BeanFactory 는 스프링 컨테이너에 최상위 인터페이스
- BeanFactory 는 getBean 을 제공한다
- ApplicationContext 는 애플리케이션할때 빈을 관리하고 조회기능등등 부가기능이 추가되었다.
- 부가기능 - 언어변환,환경변수,이벤트,리소스조회..
정리
- ApplicationContext 는 BeanFactory 기능을 상속받는다
- ApplicationContext 는 빈기능 + 편리한 부가기능
- BeanFactory , ApplicationContext 를 스프링 컨테이너라고 한다.
7.다양한 설정 형식 지원 - 자바코드 , XML
- 자바코드 , xml , Groovy 설정가능
- 자바코드설정
- AnnotationConfigApplicationContext 를 이용해서 설정
- xml
- GenericXmlApplicationContext 를 이용
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="memberService" class="hello.Study_Spring.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
</bean>
<bean id="memberRepository"
class="hello.Study_Spring.member.MemoryMemberRepository" />
<bean id="orderService" class="hello.Study_Spring.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
<constructor-arg name="discountPolicy" ref="discountPolicy" />
</bean>
<bean id="discountPolicy"
class="hello.Study_Spring.discount.RateDiscountPolicy" />
</beans>
@Configuration
public class AppConfig {
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy() {
//return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
}
- 두개는 똑같은 코드이다
public class XmlAppContext {
@Test
void xmlAppContext(){
ApplicationContext ac =new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService",MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
- GenericXmlApplicationContext 을 이용해서 xml 을 불러온다
- 컴파일 없이 빈설정 정보를 변경할수 있는 장점이 있다
8.스프링 빈 설정 메타정보 - BeanDefinition
- 스프링이 이렇게 다양한 설정 형식을 지원하는 중심은 BeanDefinition 가 있다
- 역할과 구현을 나눈것
- 역할 - BeanDefinition
- 구현 - xml,자바코드
- BeanDefinition 을 빈 설정메타라 한다
- 스프링컨테이너는 BeanDefinition 메타정보를 기반으로 스프링빈 생성
- 스프링 컨테이너는 BeanDefinition 만 의존한다
- 자바코드
- AnnotatedBeanDefinitionReader 를 이용해서 BeanDefinition 을 만든다
- Xml
- XmlBeanDefinitionReader 를 이용해서 BeanDefinition 을 만든다
beanDefinitionTest
public class beanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if (beanDefinition.getRole()==BeanDefinition.ROLE_APPLICATION){
System.out.println("beanDefinitionName = " + beanDefinitionName+
" beanDefinition = "+ beanDefinition);
}
}
}
}
- beanDefinition
- BeanClassName : 생성할 빈 클래스 이름
- factoryBeanName : 팩토리 역할빈 (appConfig)
- factoryMethodName : 빈을 생성할 팩토리 매서드 (memberService)
- Scope : 싱글톤(기본값)
정리
- beanDefinition 을 직접 생성해서 스프링 컨테이너에 등록 할수있다
- beanDefinition 을 이용해서 스프링의 다양한 형태의 설정 정보를 추상화 해서 사용한다
728x90
'Back-End > Spring' 카테고리의 다른 글
6.컴포넌트 스캔 (0) | 2021.01.07 |
---|---|
5.싱글톤 컨테이너 (0) | 2021.01.05 |
3.스프링 핵심 원리 이해2 - 객체지향원리적용 (0) | 2021.01.01 |
2.스프링 핵심 원리 이해1 - 예제만들기 (0) | 2020.12.31 |
1.객체지향설계와 스프링 (0) | 2020.12.30 |