Spring 04 - Spring Container


스프링 컨테이너

스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트이며 컨테이너가 하는 기능은 다음과 같다.

  • 자바 객체(Bean)의 생명 주기를 관리
  • 생성된 자바 객체에 추가적인 기능 제공

즉, 개발자가 직접 만들고 관리하는 것이 아닌 스프링 컨테이너를 이용하여 관리해주는 공간이라 말할 수 있다.

왜 스프링 컨테이너를 사용?

JAVA를 이용하여 직접 개발할 때 new를 통해 객체를 생성하여 개발을 할 것이다. 이렇게 생성된 객체들이 많이 존재하다 보면, 서로가 서로르 참조하게 될 것이고, 이는 의존성이 높아지는 현상이 발생할 수 밖에 없다.
이를 막기 위해 스프링 컨테이너를 사용하여 객체의 생명주기를 관리함으로써 의존성을 낮추는 개발을 할 수 있게 된다.

스프링 컨테이너 종류

Container

크게 2가지 인터페이스로 구성이 되어 있다.

  • BeanFactory
    • 스프링 컨테이너 최상위 인터페이스
    • Bean의 등록 생성 조회 등 Bean의 생성주기를 관리하는 역할
    • getBean()을 호출하여 Bean을 가져올 수는 있다.
  • ApplicationContext
    • BeanFactory의 기능을 상속받아 제공 + 추가 기능 제공
    • 추가 기능들
      • MessageSource : 메시지 다국화용 인터페이스
      • EnvironmentCapable : 개발, 운영, 환경변수 등으로 나누어 처리하고, 애플리케이션 구동 시 필요한 정보들을 관리하기 위한 인터페이스
      • ApplicationEventPublisher : 이벤트 관련 기능을 제공하는 인터페이스
      • ResourceLoader : 파일, 클래스 패스, 외부 등 리소스를 조회 인터페이스
    • // ApplicationContext interface
      public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver
      

스프링 개발시 주로 BeanFactory를 사용하는 대신, ApplicationContext를 사용하여 Bean관리 기능 외 다른 필요한 부가기능을 편히 사용할 수 있게 된다.

또한 BeanFactory와 ApplicationContext의 차이점은 Bean 생성 시기 차이이다. BeanFactory에서 Bean객체 생성 시점은 getBean()을 호출했을 때이고, ApplicationContext는 App실행 시 Context초기화 시점에 미리 생성이 된다.

스프링 컨테이너 수동 설정 방법

스프링 컨테이너를 설정하는 방법은 XML파일로 설정이 가능했었지만, 이제 스프링 부트가 들어온 이후부턴 자바 클래스에서 설정이 가능해졌다.

사용 방법은 다음과 같다.

  1. ApplicationContext의 구현체인 AnnotationConfigApplicationContext와 @Configuration이 적용된 클래스파일을 이용해서 ApplicationContext 객체 생성
  2. @Configuration이 적용된 ApplicationContext 클래스 내에서는 @Bean으로 설정된 Bean객체 반환 메서드 존재
  3. applicationContext내 bean을 가져오기 위해 getBean()을 호출
// main 실행 함수 내...
ApplicationContext applicationContext = 
    new AnnotationConfigApplicationContext(ApplicationConfig.class);

ConveniencePayService conveniencePayService =
    applicationContext.getBean("conveniencePayService", ConveniencePayService.class);

// ApplicationConfig 클래스 (@Configuration)
@Configuration
public class ApplicationConfig {

    @Bean
    public ConveniencePayService conveniencePayService(){
        return new ConveniencePayService(
                new HashSet<>(Arrays.asList(moneyAdapter(), cardAdapter())),
                discountByConvenience()
        );
    }

    @Bean
    public ConveniencePayService methodPayService(){
        return new ConveniencePayService(
                new HashSet<>(Arrays.asList(moneyAdapter(), cardAdapter())),
                discountByPayMethod()
        );
    }
    ...
}

@Configuration

  • 스프링 컨테이너가 해당 어노테이션이 붙은 클래스를 설정 정보로 사용
  • 클래스 내부에 @Bean 어노테이션이 적힌 메서드를 모두 호출하여 얻은 객체를 스프링 컨테이너에 등록하게 된다.

스프링 컨테이너 자동 설정 방법

ApplicationContext를 생성하여 @Configuration으로 된 클래스를 이용하는 방법이 있지만, 스프링 부트에서는 @ComponentScan과 @Component로 스프링 컨테이너를 자동으로 설정하고 Bean을 생성할 수 있다.

// 스프링 부트로 자동으로 만들어진 SimpleBoardApplication
@SpringBootApplication
public class SimpleBoardApplication {

	public static void main(String[] args) {
		SpringApplication.run(SimpleBoardApplication.class, args);
	}

}
// @SpringBootApplication 내부엔 @ComponentScan이 존재
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    ...
}

// SimpleBoardApplication 패키지 및 하위 패키지 내 @Component
// @Service, @Repository, @Controller는 @Component을 포함하고 있다.
@Service
public class BoardService {
    ...
}

// @Service, @Repository, @Controller 내부엔 @Component가 존재
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}


@ComponentScan

  • 이 어노테이션이 적용된 해당 클래스의 패키지와 하위 패키지에 있는 @Component 어노테이션이 포함된 클래스들을 탐색하여 Bean으로 등록해주는 어노테이션
  • @Service, @Repository, @Controller 어노테이션들 그리고 @Configuration도 내부적으로 @Component를 포함하고 있으므로 이 어노테이션으로 된 클래스도 Bean으로 동록이 된다.
  • 스프링 부트로 만들때 어떤 패키지 내 최상위에 있는 어떤Application로 된 클래스가 main함수로 생기는데, 그 때 박혀진 @SpringBootApplication내에 @ComponentScan이 존재하고 있다. 이는 어떤Application 실행 시 해당 패키지 및 하위 클래스 내 모든 컴포넌트를 bean으로 등록해준다!

@Component

  • 클래스 레벨에서 선언함으로써 스프링이 런타임시에 @ComponentScan에 의해 자동으로 빈으로 등록됨
  • @Service, @Repository, @Controller 어노테이션들 그리고 @Configuration도 내부적으로 @Component를 포함됨

Next

그래서 다음은..
@bean…