Spring 04 - Spring Container
in Web-Programming on Spring
스프링 컨테이너
스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트이며 컨테이너가 하는 기능은 다음과 같다.
- 자바 객체(Bean)의 생명 주기를 관리
- 생성된 자바 객체에 추가적인 기능 제공
즉, 개발자가 직접 만들고 관리하는 것이 아닌 스프링 컨테이너를 이용하여 관리해주는 공간이라 말할 수 있다.
왜 스프링 컨테이너를 사용?
JAVA를 이용하여 직접 개발할 때 new를 통해 객체를 생성하여 개발을 할 것이다. 이렇게 생성된 객체들이 많이 존재하다 보면, 서로가 서로르 참조하게 될 것이고, 이는 의존성이 높아지는 현상이 발생할 수 밖에 없다.
이를 막기 위해 스프링 컨테이너를 사용하여 객체의 생명주기를 관리함으로써 의존성을 낮추는 개발을 할 수 있게 된다.
스프링 컨테이너 종류
크게 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파일로 설정이 가능했었지만, 이제 스프링 부트가 들어온 이후부턴 자바 클래스에서 설정이 가능해졌다.
사용 방법은 다음과 같다.
- ApplicationContext의 구현체인 AnnotationConfigApplicationContext와 @Configuration이 적용된 클래스파일을 이용해서 ApplicationContext 객체 생성
- @Configuration이 적용된 ApplicationContext 클래스 내에서는 @Bean으로 설정된 Bean객체 반환 메서드 존재
- 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…