ApplicationContext와 빈 설정

xml 설정 파일

public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();

        // [bookService, bookRepository]
        System.out.println(Arrays.toString(beanDefinitionNames));

        // 출력된 빈 이름으로 불러온다.
        BookService bookService = (BookService) context.getBean("bookService");

        // true
        System.out.println(bookService.bookRepository != null);
    }
}

이 방법은 일일이 빈으로 등록하는 것이 굉장히 번거롭다는 것이다.

컴포넌트 스캔

그래서 등장한 것이 컴포넌트 스캔이다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="me.whiteship.springapplicationcontext"/>

</beans>
  • 지정한 패키지를 시작으로 빈을 스캔해서 등록하는 것이다.

  • 이때 기본적으로 @Component를 이용해 빈으로 등록할 수 있다.

  • @Component를 확장한 애너테이션도 있다.

    • @Service, @Repository

  • 하지만 이 과정은 단지 빈으로 등록하는 것일 뿐이다.

    • 의존성 주입은 @Autowired@Inject를 이용해 따로 해주어야 한다.

    • 단, @Inject는 다른 의존성을 필요로 하므로 주로 @Autowired를 사용해보자.

public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        String[] beanDefinitionNames = context.getBeanDefinitionNames();

        // [bookService, bookRepository]
        System.out.println(Arrays.toString(beanDefinitionNames));

        // 출력된 빈 이름으로 불러온다.
        BookService bookService = (BookService) context.getBean("bookService");

        // true
        System.out.println(bookService.bookRepository != null);
    }
}

애너테이션으로 처리하는 방법은 스프링 2.5부터 지원되었다.

자바 설정 파일

xml 대신 자바 파일로 설정하는 방법이다.

public class DemoApplication {
    public static void main(String[] args) {
        // 자바 설정 파일을 이용해 불러온다.
        ApplicationContext context =
                new AnnotationConfigApplicationContext(ApplicationConfig.class);

        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        System.out.println(Arrays.toString(beanDefinitionNames));

        BookService bookService = (BookService) context.getBean("bookService");
        System.out.println(bookService.bookRepository != null);
    }
}

아래처럼 bookService()에서 직접 의존성 주입을 하지 않고 @Autowired를 쓰는 방법도 있다.

public class DemoApplication {
    public static void main(String[] args) {
        // 자바 설정 파일을 이용해 불러온다.
        ApplicationContext context =
                new AnnotationConfigApplicationContext(ApplicationConfig.class);

        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        System.out.println(Arrays.toString(beanDefinitionNames));

        BookService bookService = (BookService) context.getBean("bookService");
        System.out.println(bookService.bookRepository != null);
    }
}
  • 직접 의존 관계를 엮지 않아도 빈으로만 등록되어 있다면 @Autowired를 사용한 의존성 주입이 이루어진다.

@ComponentScan 애너테이션

컴포넌트 스캔은 전부 알아서 찾아주니까 편했는데 자바 설정 파일을 쓰니까 하나하나 빈으로 등록해야 해서 불편하다. 이때 @ComponentScan을 사용할 수 있다.

@Configuration
// basePackages는 일일이 패키지 이름을 써줘야 하므로 오타로 에러가 날 확률이 있다.
// 하지만 basePackageClasses를 쓰면 조금 더 type-safe 하다.
// 써놓은 클래스가 위치한 곳부터 컴포넌트 스캐닝을 하기 때문이다.
@ComponentScan(basePackageClasses = DemoApplication.class)
public class ApplicationConfig {
}

이 방법이 현재 트렌드에 가장 가까운 방법이다.

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {

    }
}
  • ApplicationContext를 직접 쓸 일은 없다.

  • 위처럼 @SpringBootApplication만 써주면 알아서 해준다.

  • @SpringBootApplication에 들어가보면 이미 @ComponentScan이 들어가있다.

    • 즉, 이 자체가 자바 설정 파일이므로 더 이상 ApplicationConfig.class 파일은 필요없다.

Last updated