Spring 5.0.0 M3 일 때 부터 조금씩 번역한 내용이고, 개인적으로 크게 신경안 써도 될 부분은 생략시켰습니다.
스프링의 이해 및 영어공부를 위해서 작성했었고, 소수의 필요한 분들을 위해 공유합니다.
https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/core.html#spring-core
1. IoC 컨테이너
1.1 스프링 IoC 컨테이너와 빈 소개
BeanFactory 인터페이스는 모든 유형의 객체를 관리할 수 있는 고급 구성 메커니즘을 제공합니다.
ApplicationContext 는 BeanFactory의 하위 인터페이스이며, AOP기능과의 통합을 더욱 쉽게 합니다.(?)
즉, BeanFactory는 설정프레임워크와 기본 기능을 제공하고,
ApplicationContext는 더 많은 엔터프라이즈 별 기능을 제공합니다.
스프링에서 어플리케이션의 중추를 이루거나 스프링 IoC에 의해 관리되는 객체를 빈이라고 합니다.
빈은 스프링 IoC컨테이너에 의해 인스턴스화 되고 결집되는 객체입니다.
1.2 컨테이너 개요
다음 다이어그램은 스프링의 작동방식을 포괄적으로 보여줍니다.
어플리케이션 클래스들은 구성 메타 데이터와 결합되므로 ApplicationContext가 생성되고 초기화 된 후에
실행가능한 시스템 또는 어플리케이션으로 완전히 구성됩니다.
1.2.1 설정 메타데이터
스프링 IoC 컨테이너는 설정 메타데이터의 형태를 받아들입니다;
이 설정 메타데이터는 개발자가 스프링 컨테이너에게 객체를 초기화, 설정, 응집시키는 것을 지시합니다.
1.2.3 컨테이너 사용
ApplicationContext는 다른 빈과 의존성의 레지스트리를 관리할 수 있는 고급 팩토리를 위한 인터페이스이다.
Applicationcontext는 빈정의를 읽고 접근 할 수 있게 합니다.
빈 인스턴스를 getBean을 사용하여 가져올 수 있습니다. ApplicationContext 인터페이스는 빈을 가져오는 몇가지 다른 메소드도 가지고 있습니다. 그러나 이상적으로 어플리케이션 코드에 절대 그러한 메소드를 사용하면 안됩니다.
사실, 어플리케이션 코드는 getBean() 메소드를 전혀 호출하지 않아야하므로, Spring API에 전혀 의존하지 않습니다.
1.3 빈 개요
스프링 IoC 컨테이너는 한개이상의 빈을 관리합니다. 빈은 개발자가 컨테이너에게 제공한 설정 메타데이터를 가지고 생성된다. ex) XML형식의 <bean/> 정의
컨테이너 내부에서 빈 정의는 BeanDefinition 객체로 표현됩니다. BeanDefinition은 다음 메타 데이터를 포함합니다.
- 패키지 수식 클래스 이름 : 일반적으로 정의되고 있는 빈 실제의 구현클래스(?)
- 빈 (행동적인) 구성 요소 : 컨테이너에서 Bean이 어떻게 작동해야 하는지(scope, lifecycle, callbacks, 등)를 명시합니다.
- 빈이 작업을 수행하는 데 다른 빈에 대한 참조 : 이러한 참조는 collaborators 또는 종속성이라고 합니다.
- 새로 생성 된 객체에 설정할 기타 구성 설정 ex)커넥션 풀 이나 풀의 사이즈 제한을 관리하는 빈안에서 사용하는 커넥션의 수(?)
컨테이너가 autowiring과 내부 검사 단계하는 동안 적절한 판단을 하기위해서, 빈 메타데이터와 수동으로 제공되는 싱글톤 인스턴스는 가능한 한 빨리 등록될 필요가 있습니다.
기존 메타데이터와 기존 싱글토 인스턴스의 재정의는 어느정도 지원되지만 런타임시점에 새로운 빈의 등록은 공식적으로 지원되지 않으며 빈 컨테이너에서 동시성 액세스 Exception 및 일관성없는 상태가 발생할 수 있습니다.
1.3.1 빈 이름짓기
모든 빈은 하나이상의 식별자를 가진며, 식별자는 빈을 제공하는 컨테이너 안에서 유일해야합니다.
빈은 흔히 단 하나의 식별자를 가지지만, 만약 하나 이상이 요구될 경우 여분의 것들은 별칭으로 간주 될 수 있습니다.
1.3.2 빈의 인스턴스화
빈 정의는은 본질적으로 하나이상의 객체를 생성하는 방법입니다. 컨테이너는 요청을 받았을 때 명명된 빈의 recipe를 보고, 실제 객체를 생성하기위해 빈정의에 캡슐화된 설정 메타데이터를 사용합니다.
- 일반적으로 컨테이너 자체가 생성자를 반영하여 빈을 직접 생성하는 경우에 생성 될 빈 클래스를 지정하는 것은 new 연산자를 사용하는 자바 코드와 다소 동일합니다.
- 드문 경우이지만 컨테이너가 빈을 생성하기위해 정적 팩토리 메소드를 호출하는 경우, 객체를 생성하기 위해 호출 될 정적 팩토리 메소드를 포함하는 실제 클래스를 지정합니다. 스태틱 팩토리 메소드로 반환 된 객체 타입은 같은 클래스이거나 다른 클래스일 가능성이 있습니다.
inner 클래스 이름
스태틱 중첩 클래스로 빈 정의가 설정되길 원한다면 중첩 클래스의 binary 이름을 사용해야 합니다. ex)com.example.Foo$Bar
생성자로 인스턴스화 하기
생성자 접근에 의해 빈을 생성할 때, 모든 일반 클래스는 스프링에 의해 사용가능하고, 호환가능하다. 즉 개발중인 클래스는 특정 인터페이스를 구현하거나 특정방식으로 코딩 할 필요가 없습니다. 빈클래스를 지정하는 것만으로 충분합니다. 그러나 특정 빈을 사용하는 IoC 유혀에 따라, 기본 생성자가 필요할 수 있습니다.
스프링 IoC 컨테이너는 관리하고자 하는 특정 클래스를 사실상 관리할 수 있습니다; true 자바빈을 관리하는것에 제한되지 않습니다. 대부분의 스프링 유저는 단 하나의 기본 생성자와 [컨테이너의 속성 다음에(?)] 적절한 setter, getter로 설계 된 실제 자바빈을 선호합니다. 또한 컨테이너에서 이례적으로 빈 스타일이 아닌 클래스를 가질 수 있습니다.
스태틱 팩토리 메소드를 이용한 인스턴스화
인스턴스 팩토리 메소드를 이용한 인스턴스화
1.4 의존성
일반적으로 엔터프라이즈 어플리케이션은 단일 객체(스프링용어로 빈)로 구성되지 않습니다. 심지어 가장 간단한 어플리케이션이라도 최종 사용자가 일관된 어플리케이션으로 보는 것을 제시하기 위해 함께 작동하는 몇가지 객체가 있습니다. 다음 섹션에서는 목표를 이루기 위해 객체들이 협력하여 완전히 구현된 어플리케이션에서 독립적으로 다수의 빈을 어떻게 정의하는지 설명합니다.
1.4.1 의존성 주입(DI)
의존성 주입(DI)은 객체들이 같이 동작할 객체의 의존성을 생성자나 팩토리메서드로 생성되거나 팩토리 메서드에서 리턴된 객체 인스턴스에 설정된 프로퍼티만으로 정의하는 과정이다. 그런 다음 컨테이너는 빈을 생성할 때 의존성을 주입한다. 이 과정은 근본적으로 역전으로, 인스턴스 생성을 제어하는 빈 자체의 IoC 또는 클래스의 직접적인 생성이나 서비스 로케이터 패턴을 사용하여 자체 종속성의 위치를 결정할 수 있습니다. ( 밍 : 사용자가 해야할 일을 컨테이너가 위임받아 한다는 뜻)
코드는 DI원리로 더욱 깨끗해지고 객체가 의존성을 제공받을 때 더욱 효과적으로 분리됩니다. 이 객체는 의존성을 찾을 수 없고 의존성의 위치나 클래스를 알수 없습니다. 이와 같이 클래스는 더욱 쉽게 테스트되며, 특히 의존성이 인터페이스나 abstract base classes 있을 때 단위 테스트에서 stub 또는 mock을 사용할 수 있습니다.
DI는 생성자 기반의 의존성 주입과 setter 기반의 의존성 주입이라는 두가지 주요한 variants를 가지고 있습니다.
생성자 기반의 의존성 주입
생성자 기반 DI는 여러개의 인수를 가진 생성자를 호출하는 컨테이너에 의해 수행되며, 각각의 생성자는 종속성을 나타냅니다. 다음 예제는 생성자 주입으로만 DI하는 클래스를 보여줍니다. 여기에는 이 클래스에 대한 어떤 특별한 것도 없다는 것에 유념해야 하며, 컨테이너 고유의 인터페이스, 기본클래스 또는 어노테이션에 의존하지 않는 POJO(Plain Old Java Object)입니다.
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; }
// business logic that actually uses the injected MovieFinder is omitted...
}
생성자 인수 결정
인수의 타입을 이용하여 생성자 인수를 결정합니다. 빈정의의 생성자 인수가 잠재적 모호성이 없으면 빈이 인스턴스화 될 때, 빈 정의에서 생성자 인수가 정의되는 순서는 해당 인수가 적절한 생성자에게 제공되는 순서입니다.
Setter 기반 의존성 주입
Setter 기반 DI는 컨테이너가 빈을 인스턴스화하기 위해 인수가 없는 생성자 또는 인수가 없는 정적 팩토리 메소드를 호출한 후, 빈에 있는 Setter메소드를 호출함으로써 수행됩니다.
AppicationContext는 자신이 관리하는 빈에 대한 생성자 기반 및 Setter 기반의 DI를 제공합니다. 또한 일부 의존성이 이미 생성자 접근을 통하여 주입된 후에도 Setter 기반의 DI를 제공합니다. PropertyEditor 인스턴스와 함께 사용하여 다른 형식으로 속성을 변환하는BeanDefinition 형식으로 의존성을 구성합니다.(?) 그러나 대부분의 스프링 유저들은 이러한 클래스를 직접적으로 사용하지 않고 XML 빈 정의, 어노테이션 컴포턴트(@Component, @Controller, etc), 자바기반의 @Configuration 클래스 @Bean 메소드를 사용합니다. 이러한 소스는 내부적으로 BeanDefinition의 인스턴스로 변환되어 전체 Spring IoC 컨테이너 인스턴스를 로드하는데 사용됩니다.
생성자 기반? Setter 기반 DI?
생성자 기반과 setter기반 DI를 섞어서 사용할 수 있으므로, 선택적 의존성으로는 setter메소드나 설정 메소드는 사용하고 필수적 의존성을 위해서는 생성자를 사용하는 것이 좋은 방법입니다. Setter 메소드에서 @Required 어노테이션을 사용하면 속성을 필수 의존성으로 만들 수 있습니다.
스프링 팀은 일반적으로 어플리케이션 component를 불변객체로 구현하고 필요한 종속성이 null이 아닌지 확인하기 위해 생성자 삽입을 장려합니다. 게다가 생상자 주입 components는 항상 전적으로 초기화 된 상태에서 클라이언트(호출한)코드로 반환됩니다. 부가적으로 많은 수의 생성자 인자는 클래스가 많은 책임을 가지고 있을 가능성이 있고, 적절히 관심을 분리하기 위해 리팩토링 되어야 함을 의미하기 때문에 많은 수의 생성자 인자는 좋지 못한 코드 향을 풍깁니다.
Setter 주입은 주로 클래스내에서 합당한 기본값을 할당 받을 수 있는 선택적 의존성으로만 사용되어야 합니다. 그렇지 않으면 이 코드가 의존성을 사용하는 모든곳에서 not-null 확인작업이 수행되어야 합니다. Setter주입의 한가지 이점으로는 Setter메소드가 나중에 해당 클래스의 객체를 재구성하거나 다시 주입 할 수 있게 만드는 것입니다.
특정 클래스에 가장 적합한 DI 스타일을 사용해야하며, 간혹, 소스가 없는 제3자 클래스를 다룰 때는어떤 DI를 선택할 지 선택해야 합니다.
의존성 해결 과정
컨테이너는 다음과 같이 빈 의존성 해결을 수행합니다.
- ApplicationContext는 모든 빈들을 설명하는 설정 메타데이터를 가지고 생성 및 초기화 됩니다.
- 기본 생성자 이외의 것을 사용하려면 각 빈에 대해 의존성은 속성, 생성자 인자 또는 스태틱 팩토리 메소드 인자의 형식으로 표현된다. 의존성은 빈이 실제로 생성될 때 빈에게 제공됩니다.
- 각 속성 또는 생성자 인자는 값을 설정하는 실제 정의이거나 컨테이너의 다른 빈에 대한 참조입니다.
- 값이 있는 속성이나 생성자 인자는 속성 또는 생성자 인자의 실제 타입의 형식으로 변환됩니다. 기본적으로 스프링은 문자열 형식으로 제공 된 값을 int, long, String, boolean 등과 같은 모든 내장 유형으로 변환 할 수 있습니다.
스프링 컨테이너는 컨테이너가 생성될 때 각 빈의 설정의 유효성을 검사합니다. 그러나 빈 속성 그 자체는 빈이 실제로 생성될 때까지 설정되지 않습니다. 컨테이너가 생성될 때, 싱글톤 스코프 이면서 미리 인스턴스화 되도록 설정 된 빈(기본값)이 생성됩니다. 그렇지 않으면, 요청 된 경우에만 빈이 생성됩니다. 빈을 생성하면서 빈의 의존성과 의존성에 대한 의존성(등등)이 생성되고 할당되는 것과 같은 빈의 그래프를 야기합니다.
일반적으로는 스프링이 올바르게 작동한다고 믿을 수 있습니다. 그리고 스프링은 컨테이너가 로드될 때 존재하지 않는 빈이나 순환 의존성을 참조와 같은 설정 문제들을 감지합니다. 빈이 실제로 생성될 때, 가능한 늦게 속성을 설정하고 의존성을 해결합니다. 즉, 오브젝트나 의존성을 생성하는데 문제가 발생한다면 올바르게 작동 된 스프링 컨테이너는 객체를 요청할 때 예외를 만들어 냅니다. 일부 설정 문제에 대한 가시성을 잠재적으로 지연시키는 이유는 ApplicationContext 구현이 기본적으로 빈을 미리 인스턴스화하기 때문입니다. 빈이 실제로 필요하기 전에 빈을 생성하기위해 약간의 시간과 메모리를 들여서 ApplicationContext가 생성될 때 설정 문제를 발견 할 수 있습니다. 그리고 싱글톤빈이 미리 인스턴스화되기보다는 지연 초기화 될 수 있도록 이러한 기본 동작을 무시할 수 있습니다.
순환 의존성이 존재하지 않으면 하나이상의 협업 빈이 의존빈으로 주입될 때, 각 협업 빈은 의존성 빈에 주입되기 전에 완전히 생성됩니다. 이것은 빈 A가 빈 B에 의존성을 가지고 있으면 스프링 IoC 컨테이너는 빈 A에 Setter메소드를 호출하기 전에 빈 B를 생성한다는 것을 의미합니다.
1.4.2 의존성과 설정에 대한 세부사항
1.4.3 의존성 사용
하나의 빈이 다른빈과 의존성을 갖고있다는 것은 일반적으로 빈이 다른 빈의 속성으로 설정된다는 것을 의미합니다. 그러나 때로는 빈 사이의 의존성은 직접적이지만은 않습니다. 예를 들면 데이터베이스 드라이버 등록처럼 클래스의 스태틱 초기화가 실행되어야 합니다. depends-on 속성은 이 요소를 사용하는 빈이 초기화 되기 전에 하나이상의 빈을 초기화되도록 명시적으로 강제할 수 있습니다.
1.4.4 지연 초기화된 빈
기본적으로 ApplicationContext 기능은 초기화 프로세스의 일부로서 모든 싱글 톤 빈을 열심히 만들고 설정합니다. 일반적으로 미리 초기화된 빈이 바람직합니다. 왜냐하면 몇시간, 며칠 후가 아니라 즉시 설정이나 주변 환경의 오류가 발견되기 때문입니다. 이러한 동작이 바람직하지 않을 때에는 빈정의를 지연 초기화로 표시함으로써 싱글톤빈이 미리 인스턴스화되는 것을 막을 수 있습니다. 지연 초기화된 빈은 IoC 컨테이너에게 시작할 때가아닌 처음으로 호출될 때 빈 인스턴스를 생성하라고 지시합니다.
1.4.5 협력객체의 자동연결(Autowiring)
스프링 컨테이너는 협력 빈사이의 관계를 자동연결(autowire) 할 수 있습니다. 스프링이 ApplicationContext의 내용을 검사함으로써 당신의 빈을 위해 자동적으로 다른 빈들을 분석하도록 할 수 있다. Autowiring은 다음의 이점이 있습니다.
- Autowiring 은 속성이나 생성자의 인자 지정할 필요성을 크게 줄여줍니다.
- Autowiring은 객체가 변할 때 설정을 변경할 수 있습니다. 클래스에 의존성을 추가할 필요가 있다면 설정을 수정할 필요없이 자동적으로 의존성을 만족시킬 수 있습니다. 그러므로 Autowiring은 코드 기반이 보다 안정적일 때 명시적인 연결으로 전환 없이 개발 중에 특히 유용하게 사용할 수 있습니다.
Autowiring의 한계와 단점
Autowiring은 프로젝트 전반에 일관적으로 사용 될때 가장 잘 작동합니다. Autowiring이 일반적이지 않게 사용된다면 한두개의 빈정의를 연결하기위해 사용하려는 개발자에게는 혼란스러울 수 있습니다.
1.4.6 메소드 주입
대부분의 어플리케이션 상황에서 컨테이너안에 있는 대부분의 빈은 싱글톤이다. 싱글톤빈이 다른 싱글톤빈과 또는 비싱글톤빈이 다른비싱글톤빈과 협력이 필요할 때는 일반적으로 하나의 빈을 다른 빈의 특성으로 정의하여 의존성을 맺습니다. 빈의 생명주기가 다른경우에 문제가 발생합니다. 싱글톤 빈 A가 비싱글톤(프로토타입) B를 필요로 하고 아마 각메소드 호출은 A에서 일어난다고 가정해보면, 싱글톤 빈 A를 한번만 생성하기 때문에 속성을 한번만 설정할 수 있습니다. 컨테이너는 필요할 때마다 빈 A에 빈 B의 새로운 인스턴스를 제공할 수 없습니다.
해결책은 제어의 역전을 막는것입니다. ApplicationContextAware 인터페이스를 구현함으로써 빈 A를 컨테이너에 인식시킬 수 있고, 컨테이너에서 getBean("B")을 호출함으로써 빈A가 필요할 때마다 빈 B 인스턴스를 요청 할 수 있습니다.
메소드 주입 검색
메소드 주입 검색은 컨테이너 내에서 다른 이름의 빈의 검색결과를 리턴하기 위해 컨테이너가 관리하는 빈의 메소드를 오버라이드합니다. 이 검색은 일반적으로 프로토타입빈을 포함한다. 스프링 프레임워크는 동적으로 메소드를 오버라이드 하는 서브클래스를 생성하기위해 CGLIB 라이브러리로부터 바이트코드를 생성하여 메소드 주입을 행합니다.
이전 코드에서 CommandManager를 보면 스프링 컨테이너가 동적으로 createCommand() 메소드의 구현을 오버라이드 하는 것을 볼 수 있습니다.
1.5 빈 스코프
BeanDefinition을 생성할 때 BeanDefinition에 의해 정의된 클래스의 실제 인스턴스를 만들기위한 recipe를 생성한다. BeanDefinition이 recipe라는 개념은 클래스와 마찬가지로 하나의 recipe로 부터 여러 개의 객체 인스턴스를 생성할 수 있기 때문에 중요합니다.
특정 빈 정의에서 생성 된 객체에 연결할 다양한 종속성 및 설정 값뿐만 아니라, 특정 bean 정의에서 생성 된 객체의 범위를 제어 할 수 있습니다.이러한 접근은 자바 클래스 수준에서 객체의 범위를 정하지 않고 설정을 통해 생성하는 객체의 범위를 선택할 수 있다는 관점에서 강력하고 유연합니다. 빈은 많은 범위들 중 하나로 배포되도록 정의될 수 있습니다.즉 스프링 프레임 워크는 여섯개의 범위를 지원하며, 다섯개는 web-aware ApplicationContext를 사용하는 경우에만 사용할 수 있습니다.
3.빈 범위 테이블
Scope |
Description |
(기본값) 한번만 인스턴스 생성 |
|
호출될 때마다 인스턴스 생성 |
|
HTTP 요청당 생성 |
|
Session 당 생성 |
|
ServletContext 당 생성 |
|
webSocket 당 생성 |
스프링 3.0 이후부터는 스레드 스코프로도 이용 가능하지만 기본값으로 등록될 수는 없습니다.
(SimpleThreadScope 참조)
1.5.1 Singleton 범위
Singleton 빈 하나의 공유 인스턴스만 관리 되며, 해당 빈 정의와 일치하는 id가 있는 빈에 대한 모든 요청은 하나의 특정 빈 인스턴스가 스프링 컨테이너에 의해 리턴됩니다.
다시말해서 빈정의를 정의, Singleton으로 범위를 지정하게 되면, 스프링 IoC 컨테이너는 정확히 빈 정의에 의해 정의된 객체의 하나의 인스턴스를 생성합니다. 이 하나의 인스턴스는 Singleton 빈의 캐시에 저장되고, 그 이후의 모든 요청과 해당 빈에 대한 참조는 캐시 된 객체를 리턴합니다.
스프링의 싱글톤 개념은 GoF 패턴책에 정의된 싱글톤 패턴과는 다릅니다. GoF의 싱글톤은 객체의 범위를 하드코딩하여 클래스로더 별로 하나의 특정 클래스 인스턴스만을 생성하지만, 스프링 싱글톤의 범위는 컨테이너, 빈 별로 생성됩니다. 이것은 단일 스프링 컨테이너안에서 특정한 클래스에 대해 하나의 빈을 정의하면 스프링 컨테이너는 빈 정의에 의해 정의된 단 하나의 빈을 생성한다는 것을 의미합니다. 싱글톤은 스프링에서 기본값이고, XML에서 싱글톤으로 빈을 정의 하기위해서는 아래와 같이 쓰면 됩니다.
default scope in Spring. To define a bean as a singleton in XML, you would write, for example:
<bean id="accountService" class="com.foo.DefaultAccountService"/>
<!-- the
following is equivalent, though redundant (singleton scope is the default)
-->
<bean id="accountService"
class="com.foo.DefaultAccountService" scope="singleton"/>
1.5.2 prototype 범위
비 싱글톤인 빈의 프로토타입 범위는 지정한 빈이 만들어지기 위해 요청할 때마다 새로운 인스턴스를 생성합니다. 즉, 프로토타입 빈은 다른 빈으로 주입되거나 컨테이너의 getBean() 메소드 호출을 통해서 요청됩니다. 일반적으로는 stateful 빈은 프로토타입 범위를 사용하고 stateless한 빈에는 싱글톤 범위를 사용하세요.
다음 그림은 스프링 프로토타입 범위를 보여줍니다. 일반적으로 DAO는 conversational 상태를 유지하지 않기 때문 DAO는 프로토타입으로 구성되지 않습니다.
다른 스코프와 반대로 스프링은 프로토타입 빈의 완전한 생명주기를 관리하지 않습니다. 컨테이너는 프로토 타입 객체를 인스턴스화, 구성 및 응집한 다음에 프로토 타입 객체를 더 이상 관리하지 않고 클라이언트에 전달합니다. 그러므로 초기화 생명주기 콜백 메소드는 범위에 관계없이 모든객체에서 호출되지만 프로토타입의 경우 구성된 라이프 사이클 콜백은 호출되지 않습니다. 클라이언트 코드는 반드시 프로토타입 범위로 지정된 객체를 정리해야하며, 프로토타입 빈이 가지고있는 비싼 자원을 해제해야 합니다. 스프링 컨테이너가 프로토 타입 빈이 가지고있는 자원을 해제하기 위해서는 정리가 필요한 빈에 대한 참조를 보유하고 있는 사용자 정의 빈 전 처리기를 사용해보시길 바랍니다.
어떤면에서, 프로토타입 빈에 관한 스프링컨테이너의 역할은 자바 new 연산자가 대신합니다. 이시점을 지난 모든 라이프 사이클의 관리는 클라이언트가 처리해야합니다.
1.5.3 프로토 타입에 의존성을 가지는 싱글톤빈
포로토타입에 의존적인 싱글톤 범위의 빈을 사용할때 인스턴스화 될때 의존성이 해결(?)된다는 것에 유의해야 합니다. 그러므로 프로토타입 범위의 빈을 싱글톤 범위의 빈에 DI를 하면 새 프로토타입 빈이 인스턴스화 된 다음 싱글톤 빈에 DI가 됩니다. 프로토타입 인스턴스는 싱글 톤 범위의 빈에 제공되는 유일한 인스턴스입니다.
그러나 런타임시 싱글톤 범위의 빈이 반복적으로 새 프로토타입 범위의 빈을 얻기를 가정하면, 스프링 컨테이너는 싱글톤 빈을 인스턴스화 하고, 의존성을 해결하고 주입할 때 주입은 한번에 한번만 일어나기 떄문에 프로토타입 범위의 빈을 싱글톤 빈으로 주입할 수 없습니다. 런타임시에 하나 이상의 프로토타입 빈의 새 인스턴스가 필요하면 메소드 주입을 확인해보세요.
1.5.4 Request, session, application, WebSocket 범위
Request, session, application websocket 범위는 web-aware Spring ApplicationContext 구현( XmlWebApplicationContext 같은)을 사용할 때에만 가능하다. ClassPathXmlApplicationContext 같은 일반적인 스프링 IoC 컨테이너에서 이러한 범위를 사용하면 알 수 없는 빈 범위에 고나한 IllegalStateException이 발생할 것입니다.
초기 웹 설정
Request, session, application, websocket 레벨(웹 범위의 빈)에서 빈의 범위를 지원하기위해서는 빈을 정의하기 전에 약간의 초기 설정이 필요합니다. (이 초기설정은 표준 범위인 싱글톤과 프로토타입에서는 필요하지 않습니다.)
이 초기 설정을 수행하는 방법은 특정 서블릿 환경에 따라 다릅니다.
스프링 웹 MVC안에서 범위 빈을 접근하면 사실상 요청은 스프링 DispatcherServlet에 의해 처리됩니다. 그러고 어떤 특별한 설정도 필요하지 않습니다. (DispatcherServlet은 이미 모든 관련 상태를 노출합니다.)
서블릿 2.5 웹 컨테이너를 사용하고, Spring의 DispatcherServlet 외부에서 요청이 처리되는 경우(예를들면 JSF 나 Struts를 사용할 때) RequestContextListener를 등록해야합니다. Servlet 3.0+에서 이 작업은 WebApplicationInitializer 인터페이스를 통해 계획적으로 수행 할 수 있습니다.
DispatcherServlet, RequestContextListener, RequestContextFilter 모두 똑같은 일을 합니다. 즉, 요청을 처리하는 스레드에 HTTP 요청 객체를 바인딩합니다. 이렇게하면 request 및 session 범위에 있는 빈을 호출 체인에서 사용할 수 있습니다.
Request scope
빈 정의에 대해 다음 XML 설정을 사용합니다.
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
스프링 컨테이너는 각각의 모든 HTTP request에 대해서 loginAction빈 정의를 사용하여 LoginAction의 새로운 인스턴스를 생성합니다. 즉 loginAction 빈은 HTTP request 레벨로 범위지정이 되어있습니다. 같은 loginAction 빈 정의로 부터 생성된 다른 인스턴스들은 상태안에서 이러한 변경을 감지하지 못하기 때문에 원하는 만큼 생성된 인스턴스의 내부상태를 변경할 수 있습니다. 그것은 개별적인 요청사항에 특히 중요합니다. 요청이 처리를 완료하면 request로 지정된 빈은 버려집니다.
Session scope
빈 정의에 대해 다음 XML 설정을 사용합니다.
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
스프링 컨테이너는 단일 HTTP Session의 수명동안 userPreferences 빈 정의를 사용함으로써, UserPreferences 빈의 새로운 인스턴스를 생성합니다. 다시말해서, userPreferences빈은 HTTP Session으로 유효 범위가 지정됩니다. request scope로 지정된 빈처럼 당신이 원하는 만큼 생성된 인스턴스의 내부상태를 변경시킬 수 있습니다. 그리고 동일한 userPreferences 빈 정의에서 생성 된 인스턴스를 사용하는 다른 HTTP Session 인스턴스가 이러한 내부상태 변경 사항을 볼 수 없습니다. 이유는 개별적인 HTTP 세션에만 국한되기 때문입니다. HTTP Session이 결국 없어질 때, 특정 HTTP Session으로 지정된 빈 또한 제거됩니다.
Application scope
빈 정의에 대해 다음 XML 설정을 사용합니다.
<bean id="appPreferences" class="com.foo.AppPreferences" scope="application"/>
스프링 컨테이너는 appPreferences 빈정의를 한번 사용해서 전체 웹 어플리케이션에 대해 AppPreferences의 새로운 인스턴스를 생성합니다.즉, appPreferences 빈은 ServletContext레벨로 범위가 지정되며, 일반적인 ServletContext 속성으로 저장됩니다. 이것은 다소 싱글톤 빈과 유사하지만 두가지의 다른 점이 있습니다. 첫번째로는 스프링 ApplicationContext 당 싱글톤이 아닌 ServletContext당 싱글톤(특정 웹어플리케이션에는 몇 개가 있을 수 있음)이고, 두번째로는 실제로 노출되며 따라서 ServletContext 속성으로 표시됩니다.
의존성으로 범위가 지정된 빈
스프링 IoC 컨테이너는 객체의 인스턴스화 뿐만 아니라 협동(또는 의존)객체의 연결까지 관리합니다. HTTp request 범위의 빈을 더긴 범위의 다른빈에게 주입하고 싶으면, 아마 범위지정 빈 대신에 AOP proxy로 주입하는 선택을 할 것이다. 즉, 범위가 지정된 객체와 동일한 public 인터페이스를 노출하는 proxy 객체를 주입해야 하지만, 관련 범위(예 : HTTP request)에서 실제 대상 객체를 검색하고 메소드 호출을 실제 객체에 위임할 수도 있습니다.
'Spring' 카테고리의 다른 글
AOP에 걸린 Method의 Parameter 이름 가져오기 (4) | 2018.06.19 |
---|---|
Spring Boot 1으로 Todo List를 만들어 보자 (0) | 2018.06.02 |
[MSA] #6 Spring Cloud Netflix (3) | 2018.04.19 |
스프링 빈은 Thread-safe 할까? (3) | 2017.10.15 |
Spring boot환경에서 JWT 사용하기 (11) | 2017.09.23 |