스프링 전반적인 기술을 주제로 사내 세미나를 하였다. 따라서 이를 공식 문서를 보면서 복습하면서 다시 정리해보았다.
-
스프링 코어 문서 가장 첫 부분에 나와있는 문구이다. 전체적인 기술을 다루지만 특히 스프링 프레임워크의
IoC(Inversion of Control)
컨테이너가 가장 중요하다고 나와있다. -
Spring Framework
의 IoC 컨테이너에 대한 처리는Spring
의AOP(Aspect-Oriented Programmin)
기술을 밀접하게 따르고 있다고 한다. -
스프링 프레임워크는 개념적으로 이해하기 쉽고 자바 엔터프라이즈 프로그래밍에서
AOP
요구사항의 80%를 성공적으로 해결하는AOP
프레임워크가 있다.
스프링 IoC 컨테이너 및 빈(Bean)
- 이 장에서는 제어의 반전(
IoC
) 원칙의 스프링 프레임워크 구현에 대해서 다룬다. IoC
는 의존성 주입이라고 알려져 있다.(DI)
DI
는 객체가 생성자 파라미터, 펙토리 메서드에서 반환된 후 객체 인스턴스에 설정된 속성을 통해서만 객체의 종속성을 정의하는 프로세스이다.- 그런 다음에, 컨테이너가 빈을 생성할 때, 이러한 종속성을 주입한다.
- 이러한 프로세스는 기본적으로 클래스 직접 구성이나 서비스 로케이터 패턴과 같은 매커니즘을 이용하여, 종속성의 인스턴스 화를 한다.
org.springframework.beans
와org.springframework.context
패키지들이 스프링 프레임워크IoC
컨테이너의 기본 구성을 이루고 있다.BeanFactory
인터페이스는 모든 타입의 객체를 관리할 수 있는 고급 설정 매커니즘을 제공한다.ApplicationContext
는BeanFactory
의 서브 인터페이스이다.
위와 같은 그림으로 이해하면 이해하기 편하다.
-
간단히 말해서
BeanFactory
는 구성 프레임워크와 기본 기능을 제공하며Application Context
는 더 많은 엔터프라이즈별 기능을 추가한다. -
Spring
에서는 애플리케이션의 핵심을 구성하고,Spring IoC
컨테이너에 의해서 관리되는 개체를 빈(Bean)이라고 한다. -
빈은 스프링
IoC
컨테이너에 의해서 인스턴스화, 조립 및 관리되는 객체이다. -
그렇지 않으면 빈(Bean)은 응용 프로그램의 여러 객체에 불과하다.
-
빈과 빈 사이의 종속성은 컨테이너가 사용하는 설정 메타데이터에 의해서 반영된다.
컨테이너 개요
-
org.springframework.context.ApplicationContext
는Spring Ioc
컨테이너를 나타내며 빈의 인스턴스화 및 구성 및 조립을 담당한다. -
컨테이너는 메타데이터 설정을 읽어서, 인스턴스화, 구성 및 조립할 객체에 대한 지침을 가져온다.
-
구성 메타데이터는
XML
,Java
어노테이션 또는Java
코드로 표시된다. -
애플리케이션을 구성하는 객체와 이러한 객체간의 풍부한 상호 종속성을 표현할 수 있다.
- 위의 그림은, 스프링
IoC
컨테이너가 빈 설정정보를 읽어서,ApplicationContext
생성되고 초기화되면 완전히 구성되고 실행 가능한 시스템 또는 응용 프로그램의 생성을 나타낸다.
빈의 스코프와 라이프 사이클(Bean Scope and LifeCycle)
-
스프링
IoC
컨테이너는 하나 이상의 빈을 관리한다. 이러한 빈은 컨테이너에 제공하는 메타데이터 XML<bean/>
형식으로 제공된다. -
컨테이너 자체 내에서 이러한 빈 정의는
BeanDefinition
객체로 표시되며, 여기에는 (다른 정보 중에서도) 다음과 같은 메타데이터가 포함된다.- 클래스 이름: 정의되는 빈의 실제 구현 클래스이다.
- 빈이 클래스에서 어떻게 동작해야하는지를 나타내는 동작 구성 요소이다. (범위, 라이프 사이클 콜백 등).
- 빈이 동작하는데 의존성을 가지는 다른 빈에 대한 참조이다. 이러한 참조를
collaborators
또는dependencies
라고 한다. - 새로 생성된 개체에서 설정할 기타 구성 설정(예: 풀의 크기 제한 또는 연결 풀을 관리하는 빈에서 사용할 연결 수)
위의 표는 빈의 정의를 나타내고 속성은 다음과 같다.
Class
: Bean을 생성하기 위한 클래스를 말한다.Name
: Bean의 이름을 말한다. Bean이 누군가에 의해 참조되어야 할 때 사용된다.Scope
: Bean의 생명주기와 관련하여 어느 Scope에 유일하게 존재할 것이냐에 대한 정의이다.Constructor arguements
: 빈의 생성자로 의존성을 명시 하는 방법이다.Properties
:Bean
의 생성자로 의존성을 명시하는 방법이다.Autowiring
:Autowiring
에 대한 방법을 명시하는 방법이다.Lazy initializaton
:Lazy
하게Bean
을 초기화 시키도록 명시하는 방법이다.Initialization method
:Bean
초기화 시에 호출되는 LifeCycle 메서드를 말한다.Destuction method
:Bean
파괴 시에 호출되는 LifeCycle 메서드를 말한다.
singleton
: (Default) SPRING IoC 컨테이너당 하나의 레퍼런스만 존재하는 스코프입니다.prototype
: 임의의 수의 객체 인스턴스로 단일 빈의 범위를 지정한다.request
: 단일 빈 정의의 범위를 단일 HTTP 요청의 수명 주기로 지정한다, 각, HTTP 요청에는 단일 빈 정의 뒤에 생성된 빈 인스턴스가 있다, 오직ApplicationContext
에서만 유효하다.session
: 단일 빈 정의의 범위를 HTTP 세션의 생명주기로 지정한다. 오직 웹의ApplicationContext
에서만 유효하다.application
: 단일 빈의 정의를 서블릿 컨텍스트의 생명주기에 범위를 지정한다. 웹의ApplicationContext
에서만 유효하다.websocket
: 단일bean
의 정의를WebSocket
의 생명 주기에 범위를 지정한다. 웹의ApplicationContext
에서만 유효하다.
빈의 생명 주기 콜백(Lifecycle Callbacks)
-
컨테이너의 빈 생명주기와 상호 작용하기 위해서
InitializingBean
,DisposableBean
인터페이스를 구현할 수 있다. -
컨테이너는 빈을 초기화 하기 전에
afterPropertiesSet()
을 호출하고Bean
소멸시에destory()
를 호출하여 특정 작업을 수행하게 할 수 있다.
JSR-250 스펙에서는
@PostConstruct
,@PreDestory
어노테이션을 사용하는데, 일반적으로 최신 스프링 애플리케이션에서 생명 주기 콜백을 수신하기 위한 좋은 방법이다. 어노테이션을 사용한다는 것은 스프링이 특정 인터페이스에 결합되지 않는다는 것을 의미한다.
-
내부적으로
SpringFramework
는BeanPostProcessor
구현을 사용하여 적절한 메서드를 찾아 호출할 수 있는 모든 콜백 인터페이스를 처리한다. -
커스텀 기능이 필요하거나, 스프링이 기본적으로 제공하지 않는 다른 라이프 사이클 동작이 필요한 경우
BeanPostProcessor
를 직접 구현할 수 있다.
-
InitializingBean
인터페이스는 불 필요하게 코드를 스프링에 연결하므로 사용하지 않는 것이 좋다. -
또는
@PostConstruct
주석을 사용하거나POJO
초기화 방법을 지정하는 것이 좋다. -
XML 기반 구성 메타 데이터의 경우
init-method
속성을 사용하여 인수없는 빈 서명이 있는 메서드의 이름을 지정할 수 있다. -
Java
설정으로는@Bean
의initMethod
속성을 사용할 수 있다.
public class AnotherExampleBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
// do some initialization work
}
}
여러 가지 방법으로 구현할 수 있지만, 인터페이스 방법은 권장하지 않는 방법이다.
org.springframework.beans.factory.DisposableBean
인터페이스를 구현하면 이를 포함하는 컨테이너가 소멸될 때, Bean
이 콜백을 받을 수 있다.
-
DisposableBean
인터페이스는 단일 메서드를 지정한다. -
초기화와 같이 인터페이스 구현은 불필요하게 코드를 스프링에 연결하므로 사용하지 않는 것이 좋다.
-
또는
@PreDestory
주석을 사용하거나 빈 정의에서 지원하는 일반 메서드를 지정하는 것이 좋습니다.
public class AnotherExampleBean implements DisposableBean {
@Override
public void destroy() {
// do some destruction work (like releasing pooled connections)
}
}
-
스프링 고유의
InitializingBean
또는DisposableBean
콜백 인터페이스를 사용하지 않는 초기화 및 폐기 메서드 콜백을 작성할 때는 일반적으로init()
,initialize()
,dispose()
등과 같은 이름으로 작성한다. -
이상적으로는 이러한 수명주기 콜백 메서드의 이름은, 모든 개발자가 동일한 메서드 이름을 사용하고 일관성을 보장하기 위함이다.
그렇다면 InitializingBean과 DisposableBean 인터페이스를 구현하는 것과 @PostConstruct, @PreDestory를 사용하는 것의 차이점은 무엇일까?