티스토리 뷰
반응형
[배워서 바로 쓰는 스프링 프레임워크 - www.yes24.com/Product/Goods/90051375]
1. 소개
- 이 장에서 다루는 내용
- 빈 정의 상속
- 빈 클래스의 생성자 인수를 찾는 방법
- 원시 타입(int, float 등)이나 컬렉션 타입(java.util.List, java.util.Map 등) 또는 사용자 정의 타입(Address 등)을 사용해 빈 프로퍼티나 생성자 인수를 설정하는 방법
- 빈 프로퍼티에 p-이름공간(namespace), 생성자 인수에 c-이름공간을 활용해서 XML 파일을 좀 더 간결하게 만든느 방법
- 빈 인스턴스를 생성하는 팩토리 클래스를 작성할 때 사용하는 스프링 FactoryBean ㅣㅇㄴ터페이스
- 빈 설정 모듈화하기
2. 빈정의 상속
2.1 빈 정의 상속 예제
- 애플리케이션의 여러 빈이 같은 설정 집합(프로퍼티, 생성자 인수 등)을 공유한다면 다른 빈 정의의 부모 역할을 하는 빈 정의를 만들 수 있다
- <bean> 엘리먼트의 parent 속성으로 상속할 빈 정의의 이름을 지정
- <bean> 엘리먼트의 abstract 속성을 true로 만들면 그 빈이 추상 빈이라는 뜻이다
- 추상 빈에 의존하는 빈은 정의할 수 없다
- class 속성을 지정하지 않는 빈은 꼭 추상 빈으로 만들어야 스프링 컨테이너가 그 빈 인스턴스를 생성하지 않는다
2.2 상속할 수 있는 정보
- 부모 빈 정의가 자식 빈 정의로 상속할 수 있는 생성 정보
- 프로퍼티 - <property> 엘리먼트로 설정
- 생성자 인수 - <constructor-arg> 엘리먼트 설정
- 메서드 오버라이드
- 초기화와 정리 메서드
- 팩토리 메서드 - <bean> 엘리먼트의 factory-method 속성으로 설정
- 부모 빈정의가 추상이 아닌 경우
- 부모 빈 정의가 추상이 아니어도 된다
- 자식 빈 정의에서 프로퍼티를 추가 정의할 수 있다
- 부모 빈 정의가 참조하는 클래스와 자식 빈 정의가 참조하는 클래스 사이에서 상속 관계가 존재할 수 있다
- 팩토리 메서드 설정 상속하기
- 자식 빈 정의는 빈 상속을 활용해 팩토리 메서드 정의를 부모 빈 정의에서 상속할 수 있다
3. 생성자 인수 매치하기
3.1 <constructor-arg> 엘리먼트를 사용해 빈 참조나 단순한 값 전달하기
- 생성자 인수가 간단한 자바 타입(int, String 등)이라면 <constructor-arg> 엘리먼트의 value 속성을 사용해 생성자 인수값을 지정한다
- 생성자 인수가 빈에 대한 참조라면 <constructor-arg>의 ref 속성을 사용해 빈 이름을 지정한다
3.2 타입으로 생성자 인수 매치시키기
- <constructor-arg> 엘리먼트의 index 속성을 지정하지 않으면 스프링 컨테이너는 <constructor-arg> 엘리먼트에 의해 참조되는 타입을 빈 클래스 생성자의 인수 타입과 매치 시켜서 어떤 생성자 인수를 호출할지 결정한다
- 타입이 명확히 다른 스프링 빈을 생성자 인수로 사용하기
- 타입이 근본적으로 서로 다르면(각 타입 간에 서로 상속 관계가 없다면) 타입을 모두 구분할 수 있으므로 스프링 컨테이너는 생성자에 올바른 순서로 각 빈을 주입할 수 있다
- 상속 관계인 스프링 빈들을 생성자 인수로 사용하기
- 서로 상속 관계인 빈을 구분하려면 index나 type 속성을 지정해서 어떤 <constructor-arg>를 어떤 생성자 인수로 적용할지 구별해야 한다
- 둘 이상의 생성자 인수가 같은 타입인 경우 구분할 수 있는 유일한 방법은 index thrtjddmf tkdydgksms rjt Qnsdlek
- 표준 자바 타입과 사용자 지정 타입을 생성자 인수로 사용하기
- <constructor-arg> 엘리먼트의 value 속성을 사용해 인수값 지정
- value 속성에 지정된 문자열을 가지고 변환할 수 있는 생성자 인수가 2개 이상이라면 type 속성을 사용해 생성자 인수 타입을 명확히 지정해야 한다
- 생성자 인수의 타입이 같다면(둘 이상), index 속성을 사용해 각 <constructor-arg>를 어떤 생성자 인수로 적용할지 지정하는 수 밖에 없다
3.3 이름으로 생성자 인수 매치시키기
- <constructor-arg>의 name 속성을 사용하면 <constructor-arg> 엘리먼트를 적용할 생성자 인수의 이름을 지정할 수 있다
- 이와 같은 설정은 클래스를 컴파일할 때 디버그 플래그(javac의 -g 옵션 참조)나 파라미터 이름 발견(parameter name discovery) 플래그(자바 8 이상에서 javac의 -parameters 옵션 참조)를 사용한 경우에만 쓸 수 있다
- 이 플래그들을 활성하하고 싶지 않다면 @ConstructorProperties를 사용해 생성자 인수 이름을 명시한다
- <constructor-arg> 엘리먼트와 @ConstructorProperties에서 같은 이름을 사용해야 한다
- @ConstructorProperties와 빈 정의 상속
- 부모 빈 정의에 해당하는 클래스 생성자에 @ConstructorProperties가 있으면 자식 빈에 해당하는 빈 클래스 생성자에도 반드시 @ConstructorProperties가 있어야 한다
- @ConstructorProperties와 팩토리 메서드
- 정적 팩토리 메서드나 인스턴스 팩토리 메서드에 인수를 이름으로 지정해서 넘기기 위해 @ConstructorProperties를 사용할 수는 없다
- @ConstructorProperties는 생성자만을 위한 것이므로 메서드에 @ConstructorProperties를 설정할 수 없다
- 정적 팩토리 메서드나 인스턴스 팩토리 메서드에 이름을 가지고 생성자 인수를 전달할 경우에는 디버그나 '파라미터 이름 발견' 플래그를 활성화할 수 밖에 없다
4. 다른 타입의 빈 프로퍼티와 생성자 인수 설정하기
- 스프링 PropertyEditor 구현
- 다양한 타입을 빈 프로퍼티나 생성자 인수로 쉽게 넘길 수 있도록 지원해줌
4.1 스프링 내장 프로퍼티 에디터
- 자바빈의 PropertyEditor : 자바 타입을 문자열값으로 바꾸거나 역방향으로 바꾸기 위해 필요한 로직 제공
- 스프링은 프로퍼티나 생성자의 실제 자바타입과 빈 프로퍼티나 생성자 인수의 문자열 값(<property>나 <constructor-arg>)을 상호 변환해주는 몇가지 내장 PropertyEditor를 제공한다
- 스프링 컨테이너는 등록된 PropertyEditor를 사용해 프로퍼티나 생성자 인수의 문자열값을 그에 상응하는 자바 타입으로 변환한다
- 스프링은 XML 파일에 지정한 문자열값을 빈 프로퍼티나 생성자 인수의 자바 타입으로 변환하기 위한 내장 PropertyEditor 구현을 제공한다
- CustomBooleanEditor : 문자열값을 Boolean이나 boolean 타입으로 변환한다
- CustomNumberEditor : 문자열값을 수 타입(int, long 등)으로 변환한다
- CharacterEditor : 문자열값을 char 타입으로 변환한다
- ByteArrayPropertyEditor : 문자열값을 byte[] 타입으로 변환한다
- CustomDateEditor : 문자열값을 java.util.Date 타입으로 변환한다
- PropertiesEditor : 문자열값을 java.util.Properties 타입으로 변환한다
4.2 컬렉션 타입에 값 지정하기
- java.util.Properties 타입
- <constructor-arg> 엘리먼트의 <props> 하위 엘리먼트로 설정
- <props> 엘리먼트 안에서 각 <prop> 하위 엘리먼트는 키-값 쌍을 지정
- key 속성은 키를 설정하고, <prop> 엘리먼트의 내용은 키에 해당하는 값을 설정
- java.util.List 타입
- <constructor-arg> 엘리먼트의 <list> 하위 엘리먼트로 설정
- <list> 엘리먼트 안의 각 <value> 하위 엘리먼트는 리스트에 들어갈 원소 지정
- java.util.Map 타입
- <constructor-arg> 엘리먼트의 <map> 하위 엘리먼트로 설정
- <map> 엘리먼트 하위 엘리먼트인 <entry> 엘리먼트는 Map에 저장될 키-값 쌍을 지정
- <entry> 안의 <key> 엘리먼트는 키를 설정하고 <value> 엘리먼트는 키에 해당하는 값을 설정
- java.util.Set 타입
- <constructor-arg> 엘리먼트의 <set> 하위 엘리먼트로 설정
- <set> 엘리먼트의 하위 엘리먼트인 <value> 엘리먼트는 Set에 들어갈 원소를 지정
- <list>, <set>, <map>, <prop> 엘리먼트는 자기 안에 자기 자신과 같은 타입이나 <list>, <set>, <map>, <prop>을 넣을 수 있다(키-값 쌍일 경우 키, 값 둘 다 가능)
- 스프링 빈의 참조를 List나 Set, Map 타입의 프로퍼티나 생성자 인수에 넣을 수 있다
- <ref> 엘리먼트 사용해 참조를 넣음
- 빈 이름(<bean> 엘리먼트의 id 속성으로 지정)을 List, Map, Set 타입의 생성자 인수나 빈 프로퍼티에 추가하려면 <idref> 엘리먼트를 <map>, <set>, <list> 엘리먼트 안에 사용해야 한다
- <value> 대신 <idref>를 사용하면 애플리케이션이 실행될 때 스프링 컨테이너가 sampleBean이라는 이름의 빈이 있는지 검증할 수 있다
- <null> 엘리먼트를 사용해 null 값을 Set나 List, Map 타입의 컬렉션에 추가할 수 있다
4.3 배열에 값 지정하기
- <property>, <constructor-arg> 엘리먼트 내부에 <array> 하위 엘리먼트를 사용해 배열 타입의 프로퍼티/생성자 인수 값을 설정할 수 있다
- <array> 엘리먼트의 <value> 하위 엘리먼트는 배열의 원소를 표현한다
- 배열의 배열을 만들고 싶으면 <array> 엘리먼트 안에 <array> 엘리먼트를 사용한다
4.4 <list>, <set>, <map> 엘리먼트의 디폴트 구현
- 디폴트 컬렉션 구현
- <list> - java.util.ArrayList
- <set> - java.util.LinkedHashSet
- <map> - java.util.LinkedHashMap
- 디폴트 구현이 아닌 다른 구현을 사용할 수 있음
- 스프링에서는 util 스키마에 <list>, <map>, <set> 엘리먼트를 사용할 것을 권장
- <list>, <map>, <set> 엘리먼트는 빈의 생성자 인수나 프로퍼티에 대입하려는 구체적인 컬렉션 클래스의 완전한 이름을 지정하기 위한 옵션을 제공함
5. 내장 프로퍼티 에디터
- 스프링은 빈 프로퍼티나 생성자 인수를 설정할 때 유요한 여러 가지 내장 프로퍼티 에디터를 제공한다
5.1 CustomCollectionEditor
- 원본 컬렉션 타입을 대상 컬렉션 타입으로 변환할 때 쓰임
- 기본적으로 Set, SortedSet, List 타입에 대해 등록되어 있음
- 예시 - <property>에 <set> 엘리먼트를 List로 변환할 때 CustomCollectionEditor가 LinkdeHashSet을 ArrayList로 바꿔줌
- 프로퍼티나 생성자 인수의 타입이 구체적인 컬렉션 클래스인 경우 CustomCollectionEditor는 단순히 구체적인 클래스의 인스턴스를 만들고 원본 컬렉션의 원소를 추가한다
5.2 CustomMapEditor
- 원본 Map 타입을 대상 Map 타입으로 변환
- 기본적으로 SortedMap 타입에 대해서만 등록되어 있음
5.3 CustomDateEditor
- java.util.Date 타입의 프로퍼티와 생성자 인수를 위한 프로퍼티 에디터
- java.util.Date 타입을 문자열로 형식화
- 날짜/시간을 표현하는 문자열을 parsing해서 java.util.Date 타입의 객체를 만들 때 쓰이는 사용자 지정 java.text.EdateFormat을 지원
6. 스프링 컨테이너에 프로퍼티 데이터 등록하기
- BeanWrapperImpl 클래스틑 몇 가지 내장 프로퍼티 에디터를 스프링 컨테이너에 등록한다
- 기본적으로 CustomCollectionEditor, CustomMapEditor, CurrencyEditor, ByteArrayPropertyEditor, CharacterEditor가 등록됨
- CustomDateEditor는 등록되지 않음
- CustomEditorConfigurer : 프로퍼티 에디터를 스프링 컨테이너에 등록하기 위해 사용
- 스프링의 BeanFactoryPostProcessor 인터페이스를 구현하고 스프링 컨테이너는 자동으로 CustomEditorConfigurer를 감지해 실행시킨다
- 프로퍼티 에디터를 스프링 컨테이너에 등록하는 순서
- 1. 스프링의 PropertyEditorRegistrar 인터페이스를 구현한 클래스를 만든다. 클래스는 스프링 컨테이너에 프로퍼티 에디터를 등록한다
- 2. XML 파일에 PropertyEditorRegistrar 구현을 스프링 빈으로 등록한다
- 3. XML 파일에 스프링의 CustomEditorConfigurer 특별 빈을 설정한다. 이때 1단계와 2단계에서 만든 PropertyEditorRegistrar 구현에 대한 참조를 지정한다
6.1 PropertyEditorRegistrar 구현 만들기
public class MyPropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDdateFormat("dd-MM-YYYY"), flase));
}
}
- PropertyEditorRegistrar의 registerCustomEditors 메서드는 registerCustomEditor를 사용해 스프링 컨테이너에 빈 프로퍼티 에디터를 등록하는 PropertyEditorRegistry 인스턴스를 받는다
6.2 CustomEditorConfigurer 클래스 설정하기
<bean id="myPropertyEditorRegistrar"
class="sample.spring.chapter03.beans.MyPropertyEditorRegistrar" />
<bean id="editorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property> name="propertyEditorRegistrars">
<list>
<ref bean="myPropertyEditorRegistrar">
</list>
</property>
</bean>
7. 이름공간으로 빈 정의를 간결하게 만들기
- XML 파일의 빈 정의에서 <property>와 <constructor-arg> 원소 대신에 p와 c라는 이름공간으로 빈 프로퍼티와 생성자 인수값을 지정할 수 있다
7.1 p-이름공간
- 빈 프로퍼티를 <bean> 엘리먼트의 속성으로 지정하되 이름공간을 p-이름공간으로 지정
- 빈 정의는 p 접두사를 사용해 빈 프로퍼티를 설정
- 형식
- p:<propterty-name>="<property-value>"
- p:<property-name>-ref="<bean-reference>"
- 프로퍼티 설정은 <property> 엘리먼트와 p-이름공간을 혼용할 수도 있지만 한가지로 일관성 있게 사용하는 것을 권장
7.2 c-이름공간
- 생성자 인수를 c-이름공간에 설정하려면 <bean> 엘리먼트의 속성으로 생성자 인수를 지정하되 각각의 생성자 인수를 c-이름공간 안에 지정한다
- 빈 정의는 c라는 접두사를 사용해 생성자 인수를 지정한다
- 형식
- c:<생성자-인수-이름>="<생성자-인수-값>"
- c:<생성자-인수-이름>-ref="<빈-참조>"
- 생성자 인수를 지정하기 위해 c-이름공간과 <constructor-arg> 엘리먼트를 함께 사용할 수 있지만 한가지로 일관성 있게 사용하는 것을 권장
8. util 스키마
- 스프링의 util 스키마를 사용하면 일반적인 설정 작업을 쉽게 수행할 수 있어서 빈 설정이 편해진다
- util 스키마가 제공하는 엘리먼트
- <list> : java.util.List 타입의 객체를 만들어 빈으로 노출한다
- list-class 속성 : java.util.List 인터페이스의 구체적인 클래스 지정(디폴트는 java.util.ArrayList)
- <value> 엘리먼트로 리스트에 원소 추가
- List 인스턴스를 다른 빈의 의존 관계로 지정할 수 있음
- ListFactoryBean을 대신 사용할 수도 있음
- <map> : java.util.Map 타입의 객체를 만들어 빈으로 노출한다
- map-class 속성 : java.util.Map 인터페이스의 구체적인 클래스를 지정
- <entry> 엘리먼트로 맵에 원소 추가
- Map 인스턴스를 다른 빈의 의존 관계로 지정할 수 있음
- MapFactoryBean을 대신 사용할 수 있음
- <set> : java.util.Set 타입의 객체를 만들어 빈으로 노출한다
- set-class 속성 : java.util.Set 인터페이스의 구체적인 클래스를 지정
- <value> 엘리먼트로 set에 원소 추가
- Set 인스턴스를 다른 빈의 의존 관계로 지정할 수 있음
- SetFactoryBean을 대신 사용할 수 있음
- <properties> : 프로퍼티 파일로부터 java.util.Properties 타입의 객체를 만들어 빈으로 노출한다
- location 속성 : properties 파일 위치 넣음
- Properties 인스턴스를 다른 빈의 의존 관계로 지정할 수 있음
- PropertiesFactoryBean을 대신 사용할 수 있음
- <constant> : 지정한 자바 타입에 대해 정적 공개(public, static) 필드를 만들어 노출한다
- static-filed 속성에서 지정한 값을 빈으로 노출
- 어떤 필드(public static)라도 <constant> 엘리먼트의 static-field 속성을 지정하면 스프링 컨테이너의 다른 빈이 참조할 수 있다
- FieldRetrievingFactoryBean을 대신 사용할 수 있음
- <property-path> : 빈 프로퍼티를 빈으로 노출한다
- path 속성으로 지정된 경로를 가져와서 빈 노출
- 형식 : <빈이름>.<빈프로퍼티>
- 빈을 스프링 컨텡너의 다른 빈에 주입할 수 있음
- PropertyPathFactoryBean을 대신 사용할 수 있음
- path 속성으로 지정된 경로를 가져와서 빈 노출
- <list> : java.util.List 타입의 객체를 만들어 빈으로 노출한다
9. FactoryBean 인터페이스
- 빈 인스턴스를 생성하는 클래스(팩토리 역할)는 스프링 FactoryBean 인터페이스로 구현한다
- 어떤 타입의 빈을 만들지 결정하고 복잡한 검사를 수행하며 복잡한 빈 초기화 로직을 실행하는 경우 유용하다
- FactoryBean 인터페이스에서 구현해야되는 메소드
- getObjectType : FactoryBean 구현이 관리하는 객체의 타입을 반환
- getObject : FactoryBean 구현이 관리하는 객체를 반환
- isSingleton
- true : FactoryBean 구현이 싱글턴 스코프 객체를 만드는 팩토리일 때
- 스프링 컨테이너는 getObject가 반환하는 객체를 캐시에 넣고 그 이후 객체 요청이 들어오면 캐시에 저장한 객체를 반환
- 스프링 컨테이너는 getObject를 단 한번만 호출
- false : FactoryBean 구현이 프로토타입 스코프 객체를 만드는 팩토리일 때
- 매번 객체를 요청할 때마다 getObject 메서드가 새로운 객체를 반환
- true : FactoryBean 구현이 싱글턴 스코프 객체를 만드는 팩토리일 때
- FactoryBean 자체를 스프링 컨테이너에서 얻으려면 팩토리 빈의 이름(또는 id) 앞에 &를 붙여야 한다
- ref 속성에 ref 속성이 가리키는 빈 이름 (또는 id) 앞에 &를 붙여야 됨
ex) <property name="eventSenderFactoryBean" ref="&eventSenderFactory> - 클래스에서는 &를 붙여서 얻으면됨
ex) context.getBean("&eventSenderFactory")
- ref 속성에 ref 속성이 가리키는 빈 이름 (또는 id) 앞에 &를 붙여야 됨
10. 빈 설정 모듈화하기
- 애플리케이션 설정을 구조화하거나 모듈화하기 위해 여러 XML 파일에 빈 설정을 나눠야 할 경우가 생김
- <import> 엘리먼트는 resource 속성으로 지정된 XML 파일을 임포트함
- XML 파일 위치는 <import> 엘리먼트가 위치한 XML 파일로부터 시작하는 상대적인 위치
- 스프링 컨테이너는 XML 파일에 정의된 빈을 생성하는 과정에서 의존 관계를 해결함
반응형
'study > 배워서 바로 쓰는 스프링 프레임워크' 카테고리의 다른 글
Chapter06. 애너테이션 기반 개발 (0) | 2021.07.26 |
---|---|
Chapter05. 빈과 빈 정의 커스텀화하기 (0) | 2021.07.12 |
Chapter04. 의존 관계 주입 (0) | 2021.07.11 |
Chapter02. 스프링 프레임워크 기초 (0) | 2021.05.10 |
Chapter01. 스프링 프레임워크 소개 (0) | 2021.01.16 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Spring
- 클린코드
- IntelliJ
- ddd
- docker
- docker for mac
- JavaScript
- 도커
- springboot
- gasmask
- clean code
- back merge
- gradle
- Kubernetes
- 코틀린
- kotlin
- 자바스크립트
- 자바
- 스프링부트
- java
- kotlin In Action
- QuickTimePlayer
- 쿠버네티스
- 도메인주도설계
- ImagePullBackOff
- cacheable
- k8s
- 스프링
- linuxkit
- docker pull limit
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함