Home 스프링 컨테이너와 관련된 어노테이션
Post
Cancel

스프링 컨테이너와 관련된 어노테이션

스프링 부트에서 사용되는 어노테이션 중 스프링 컨테이너와 관련된 어노테이션에 대한 글

스프링 컨테이너의 필요성

일반적인 애플리케이션이라면 여러 객체가 서로 상호 작용하면서 애플리케이션이 동작된다.
처음 Java로 프로그래밍을 입문했을떄를 아래와 같은 예시코드에서 처럼 main문에서 필요한 객체를 생성하고 조합해서, 메소드를 호출하는 형태로 프로그래밍을 시작했을 것 이다.

1
2
3
4
5
6
7
8
9
10
public class Main {

    public static void main(String[] args) {

        ClassC classC = new ClassC();
        ClassB classB = new ClassB(classC); // classB.setClassC(classC);
        ClassA classA = new ClassA(classB); // classA.setClassB(classB);       
        classA.methodA();

    }

위의 예시코드에서는 클래스가 3개 밖에 있지 않고 의존 관계가 ClassA -> ClassB -> ClassC로 단순하다.
하지만 필요한 클래스가 수십 수백개가되고, 의존관계도 복잡하다면 프로그램 실행을 위한 의존관계를 구성하고 객체를 생성하는 것이 만만치가 않다.

스프링 애플리케이션을 생각해보면 가장 쉽게 접할 수 있는 클래스인 Controller, Service, Repository 클래스가 많이 존재하고 의존 관계도 존재한다.
스프링 프레임워크는 애플리케이션 실행에 필요한 객체들의 의존 관계를 파악하고 생성해서 스프링 컨테이너에 준비한다.

스프링 컨테이너에 준비되는 객체를 Bean이라고 칭한다.

개발자가 직접 main문과 같은 소스코드를 통해서 원하는 객체를 생성하거나 주입하지 않고 스프링 컨테이너 등록되는 Bean의 명세를 바꾸는 것 만으로 실제 애플리케이션에서 사용되는 객체가 바뀌기도 하고, 각 객체간 의존 관계를 자동으로 주입해주기때문에 IoC(Inversion of Control) 컨테이너 또는 DI(Dependency Injection) 컨테이너로도 불린다.

스프링에서는 ApplicationContext가 이 역할을 한다.

스프링 컨테이너를 구성하는 여러 방법들

Desktop View 출처 : 김영한 스프링 핵심원리 기본편 스프링 컨테이너를 구성하는 방법은 여러가지가 있다.

최근에 많이 사용되는 방식은 java코드에 스프링 컨테이너와 관련된 annotation을 사용해서 등록할 객체(Bean)을 정의하는 방법이 있다. 또 xml파일에 Bean에 대한 명세를 하는 방법이 있다.

위 그림에서 보듯이 Bean을 명세하는 방식은 여러가지지만 최종적으로 명세된 정보를 바탕으로 BeanDefinition을 생성하고, 이를 통해서 스프링 컨테이너(ApplicationContext)에 Bean을 등록하게 된다.

스프링 컨테이너 구성과 관련된 어노테이션들

@Bean

1
2
3
4
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }

@Bean이 붙은 메소드의 반환 객체를 스프링 컨테이너에 등록한다.
기본적으로 메소드이름이 Bean의 이름이 된다.
name 옵션으로 이름을 변경할 수 있다. e.g. @Bean(name=”myCustomBean”)

@Component

1
2
3
4
@Component
public class MemoryMemberRepository implements MemberRepository {
        ...
}

@Component가 붙은 클래스를 ComponentScan의 스캔 대상이 되도록 한다.
기본적으로 Bean의 이름은 클래스의 이름을 사용하되 맨 앞글자만 소문자로 사용한다.(memoryMemberRepository)
value 옵션으로 이름을 변경할 수 있다. e.g. @Component(value=”memMeberRepository”)

@ComponentScan

1
2
3
@ComponentScan{
        basePackages = {"blog.core", "blog.api"}
}

@Component가 붙은 클래스를 스프링 빈으로 등록한다.
basePackages에 탐색할 패키지의 시작 위치를 지정하고, 시작 위치를 포함하여 모든 하위 패키지를 탐색하며 @Component가 붙은 클래스를 찾는다.
basePackages를 지정하지 않으면, @ComponentScan이 붙은 클래스가 위치한 패키지가 시작 위치가 된다.

@SpringBootApplication에 @ComponentScan이 포함되어있고, 일반적으로 스프링 부트를 실행하는 메인 함수가 존재하는 클래스에 붙어있고, 이 클래스는 프로젝트 루트에 존재하기떄문에 결과적으로 모든 패키지를 스캔 대상으로 하고 스프링 컨테이너가 구성된다.

@Configuration

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient(){
        return WebClient
                .builder()
                .filters(exchangeFilterFunctions -> {
                    exchangeFilterFunctions.add(logRequest());
                    exchangeFilterFunctions.add(logResponse());
                })
                .build();
    }

@Configuration으로 선언된 클래스에 정의된 @Bean을 싱글톤으로 생성해서 스프링컨테이너에 등록한다.
@Component 어노테이션을 포함하고 있으므로 @ComponentScan의 스캔 대상에 포함된다.

Refercence

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

OSIV

컨테이너간 통신 디버깅을 위한 networktool