Home 스프링 빈 조회
Post
Cancel

스프링 빈 조회

스프링 빈 조회

이전 포스팅에서 애플리케이션 컨텍스트에 대해 알아보았고 MemberFacotry를 설정정보로 사용하는 애플리케이션 컨텍스트를 만들어 보았다.

이제 애플리케이션 컨텍스트에서 빈을 가져오는 방법을 알아보자. 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.

빈 이름으로 조회

MemberFactory를 설정정보로 사용하는 어플리케이션 컨텍스트를 만들고 getBean() 메서드를 이용해 빈을 가져온다. 파라미터는 빈 메서드 명(이름)타입을 입력하면 된다.

1
2
3
4
5
6
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        MemberRepository memberRepository = context.getBean("memberRepository", MemberRepository.class);
    }
}

이름으로 검색할 때 해당하는 이름의 빈이 없는 경우가 있다. 이 때는 NoSuchBeanDefinitionException 예외가 발생한다.

빈 타입으로 조회

파라미터에서 이름을 생략할 수도 있다. 이 경우 해당 타입의 빈을 조회한다.

1
2
3
4
5
6
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        MemberRepository memberRepository = context.getBean(MemberRepository.class);
    }
}

이때 만약 동일한 타입이 둘 이상일 경우는 어떻게 될까?

동일한 타입이 둘 이상인 빈 조회

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        MemberRepository memberRepository = context.getBean(MemberRepository.class);
    }
}

@Configuration
public class MemberFactory {

    @Bean
    public MemberRepository memberRepository1() {
        return new JdbcMemberRepository();
    }

    @Bean
    public MemberRepository memberRepository2() {
        return new JdbcMemberRepository();
    }
}

결론부터 말하면 이 경우 NoUniqueBeanDefinitionException 예외가 발생 된다. 여러 해결 방법이 있고 자세한 내용은 이후 포스팅에서 설명할 예정이다. 가장 쉬운 방법은 위 예제 처럼 빈 이름을 지정하면 된다.

구체 타입으로 조회

1
2
3
4
5
6
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        MemberRepository memberRepository = context.getBean(JdbcMemberRepository.class);
    }
}

인터페이스를 상속한 구체 타입이 있을 경우 해당 구체 타입으로 조회가 가능하다. 하지만 우리는 역할과 구현을 나누고 역할에 의존해야 한다고 배웠다. 위의 코드는 역할이 아닌 구현에 의존하고 있다. 그렇기 때문에 가급적 다른 방식을 활용할 것을 추천한다.

상속관계에 있는 빈 조회

만약 빈이 상속관계에 있는 경우에 부모 타입을 조회하면 어떻게 될까? 이때는 자식 타입도 함께 조회 된다. (Object 타입으로 조회 시 모든 스프링 빈이 조회 된다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        MemberRepository memberRepository = context.getBean(MemberRepository.class);
    }
}

@Configuration
public class MemberFactory {

    @Bean
    public MemberRepository jdbcMemberRepository() {
        return new JdbcMemberRepository();
    }

    @Bean
    public MemberRepository memoryMemberRepository() {
        return new MemoryMemberRepository();
    }
}

위의 경우는 동일한 타입이 둘 이상인 빈 조회할 때와 같은 상황이다. MemberRepository에 대한 구현체 모두가 조회되기 때문에 NoUniqueBeanDefinitionException 예외가 발생 된다.

부모 타입으로 모두 조회하기

동일한 타입이 둘 이상일 경우 빈을 하나만 조회 하는 것이 아닌 모든 빈을 조회하는 방법도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MemberFactory.class);
        Map<String, MemberRepository> beanOfType = context.getBeansOfType(MemberRepository.class);

        for (String key : beansOfType.keySet()) {
            System.out.println("value = " + beansOfType.get(key));
        }
    }
}

@Configuration
public class MemberFactory {

    @Bean
    public MemberRepository jdbcMemberRepository() {
        return new JdbcMemberRepository();
    }

    @Bean
    public MemberRepository memoryMemberRepository() {
        return new MemoryMemberRepository();
    }
}

참고

This post is licensed under CC BY 4.0 by the author.

애플리케이션 컨텍스트

싱글톤 레지스트리

Comments powered by Disqus.