2022. 5. 11. 01:32ㆍSpring/개념
1 IoC 컨테이너 : 빈 팩토리와 애플리케이션 컨텍스트
스프링 애플리케이션은 오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당한다. 이를 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있다고 해서 IoC라고 부른다.
스프링 IoC 컨테이너는 일반적으로 애플리케이션 컨텍스트를 말한다. 스프링의 빈 팩토리와 애플리케이션 컨텍스트는 각각 기능을 대표하는 BeanFactory와 ApplicationContext라는 두 개의 인터페이스로 정의 되어있다. ApplicationContext 인터페이스는 BeanFactory 인터페이스를 상속한 서브 인터페이스다. ( 컨텍스트란? )
* 실제로 IoC 컨테이너라고 말하는 것은 ApplicationContext 인터페이스를 구현한 클래스의 오브젝트다!
IoC 컨테이너의 역할?
오브젝트를 생성하고 이를 관리하는 것 ( 스프링 컨테이너가 관리하는 이런 오브젝트가 빈이다 )
컨테이너에는 POJO클래스와 설정 메타정보가 필요하다. ( POJO란? )
IoC 컨테이너를 만드는 방법은 ApplicationContext 구현 클래스의 인스턴스를 만드는 것이다.
* 스프링의 메타정보는 XML 파일이아니다. 스프링이 XML에 담긴 내용을 읽어서 설정 메타정보로 활용하는 건 사실이지만, 그렇다고 해서 스프링이 XML로 된 설정 메타정보를 가졌다는 말은 틀렸다.
스프링의 메타정보는 BeanDefinition 인터페이스로 표현된 순수한 추상 정보다.
스프링 IoC 컨테이너, 즉 애플리케이션 컨텍스트는 바로 이 BeanDefinition으로 만들어진 메타정보를 담은 오브젝트를 사용해 IoC와 DI작업을 수행한다.
IoC가 사용하는 빈 메타정보
- 빈 아이디, 이름, 별칭: 빈 오브젝트를 구변할 수 있는 식별자
- 클래스 또는 클래스 이름: 빈으로 만들 POJO 클래스 또는 서비스 클래스 정보
- 스코프: 싱글톤, 프로토타입과 같은 빈의 생성 방식과 존재 범위
- 프로퍼티 값 또는 참조: DI에 사용할 프로퍼티 이름과 값 또는 참조하는 빈의 이름
- 생성자 파라미터 값 또는 참조: DI에 사용할 생성자 파라미터 이름과 값 또는 참조할 빈의 이름
- 지연된 로딩 여부, 우선 빈 여부, 자동와이어링 여부, 부모 빈 정보, 빈팩토리 이름 등
빈 등록 메타정보 구성 전략
- XML 단독 사용 - 모든 설정 정보를 자바 코드에서 분리하고 순수한 POJO 코드를 유지하고 싶다면 XML이 가장 좋은 선택이다. 애플리케이션 컴포넌트의 상당 부분이 기존에 개발됐고, 가능한 한 코드에는 손대지 않고 그대로 재사용하고 싶은 경우에도 XML 방식이 유용하다. 물론 이때는 DI에 필요한 적절한 수정자 또는 생성자가 코드에 존재해야 한다.
- XML과 빈 스캐닝의 혼용 - 애플리케이션 3계층의 핵심 로직을 담고 있는 빈 클래스는 그다지 복잡한 빈 메타정보를 필요로 하지 않는다. 대부분 싱글톤이며 클래스당 하나만 만들어지므로 빈 스캐닝에 의한 자동인식 대상으로 적절하다. 반면에 자동인식 방식으로 등록하기는 불편한 기술 서비스, 기반 서비스, 컨테이너 설정 등의 빈은 XML을 사용하면 된다. 스키마에 정의된 전용 태그를 사용해서 AOP나 트랜잭션 속성, 내장형 DB, OXM 마샬러를 위한 빈을 손쉽게 등록할 수 있다. 또한 자동인식 방식으로 설정하기 어려운 DataSource, 트랜잭션 매니저 등은 <bean> 태그를 사용해 설정할 수 있다.
- XML 없이 빈 스캐닝 단독 사용 - 애플리케이션 컨텍스트는 물론이고, 각종 기술 서비스와 컨테이너 설정용 빈도 모두 스캔으로 자동등록시키는 것이다. 이때는 자바 코드에 의한 빈 등록 방법이 반드시 필요하다. XML과 빈 자동인식의 혼합 방식에는 기존 클래스를 활용하는 기술 서비스 빈 등은 모두 XML을 활용했다. 그에 반해서 빈 스캐닝 방식에서는 주요한 컨테이너 설정과 기반 서비스를 위한 설정은 모두 자바 코드에 의한 빈 설정 방식을 사용해야 한다.
빈 의존관계 설정 방법
- XML(<property>, <constructor-arg>) - <bean>을 이용해 빈을 등록했다면 프로퍼티와 생성자 두 가지 방식으로 DI를 지정할 수 있다. 프로퍼티는 자바빈 규약을 따르는 수정자 메소드를 사용하고, 생성자는 빈 클래스의 생성자를 이용하는 방법이다. 두 가지 방법 모두 파라미터로 의존 오브젝트 또는 값을 주입해준다.
- XML(자동와이어링) - 대표적으로 이름을 사용하는 방식과 타입을 사용하는 방식 두 가지가 있다.
<bean id="hello"..>
<property name="printer" ref="printer"/>
</bean>
<bean id="printer" class="...StringPrinter"/>
- 이름을 사용하는 자동 와이어링의 경우
<bean id="hello" class="...Hello" autowire="byName">
<property name="name" value="Spring"/>
// printer프로퍼티를 생략했다. 이름으로 와이어링 해준다.
</bean>
<bean id="printer" class="...StringPrinter"/>
<beans default-autowire="byName">
...
</beans> // 문서의 모든 빈 와이어링 방식을 default를 통해 바꿀 수 있다.
- 타입을 사용하는 자동 와이어링의 경우
<bean id="hello" class="...Hello" autowire="byType"> ... </bean> // 생략했다..
<bean id="mainPrinter" class="...StringPrinter"/>
// Hello 클래스에 있는 setPrinter의 타입을 통해 자동으로 와이어링 해준다.
타입에 의한 방식은 빈의 이름이나 프로퍼티 이름에 신경쓰지 않아 편리하지만, 빈이 두 개 이상 존재할 경우 타입을 기준으로 보기 때문에 적용하지 못한다는 단점이 있다. 그리고 타입을 직접 비교해, 이름을 사용하는 와이어링 방식보다 상대적으로 느리다.
- XML(네임스페이스와 전용 태그)
- @Resource - <property> 선언과 비슷하게 주입할 빈을 아이디로 지정하는 방법이다. 자바 클래스의 수정자뿐만 아니라 필드에도 붙일 수 있다. 지금까지 살펴봤던 DI는 수정자 또는 생성자와 같은 특정 메소드를 이용했다. 하지만 @Resource를 사용하면 수정자 메소드가 없어도 직접 내부 필드에 DI 할 수가 있다.
Resource어노테이션과 XML의 자동 와이어링은 몇 가지 차이점이 있다. XML의 자동 와이어링의 경우는 주입할 만한 후보 빈이 없을 경우에 무시하지만, Resource어노테이션은 주입할 빈이 없다면 예외가 발생한다. Resource는 기본적으로 참조할 빈의 이름을 이용해서 찾는다. 그런데 만약 name 을 지정하지 않았고 참조할 빈을 찾을 수 없는 경우에는 타입을 이용해 다시 한번 빈을 찾기도 한다. @Resource를 타입으로 빈을 찾게 하는 건, 컨텍스트가 자신에 대한 레퍼런스를 직접 제공하는 다음과 같은 경우에만 적합하다. 드물지만 빈에서 애플리케이션 컨텍스트에 접근해야 할 때가 있다. 이 사용법을 제외하면 @Resource는 이름을 이용한 프로퍼티 설정이라고 기억해두는 편이 좋겠다.
@Resource(name="printer")
public void setPrinter(Printer printer) {
// name 엘리먼트를 지정 가능
}
@Resource(name="printer")
private Printer printer;
// setter 메소드 없이 쓸 수도 있다.
@Resource
private Printer printer;
// name 엘리먼트가 없어도 되긴하다.
@Resource
ApplicationContext context;
// 빈에서 애플리케이션 컨텍스트애 접근해야 할 경우
- @Autowired / @Inject - 이 두가지 애노테이션은 기본적으로 타입에 의한 자동와이어링 방식으로 동작한다. 그 의미나 사용법은 거의 동일하다. 스프링으로 개발한 POJO를 앞으로 다른 환경에서도 사용할 가능성이 있다면 @Inject와 DIJ(JSR 330 ?)에서 정의한 애노테이션을 사용하는 게 좋다. 스프링만 사용할 코드라면 어느 것을 선택해도 좋은데, 대신 한 가지 종류만 일관되게 사용하자.
public class Hello {
@Autowired private Printer printer; // 필드 주입
}
public class Hello {
private Printer printer;
@Autowired // 수정자 메소드 주입
public void setPrinter(Printer printer) {
this.printer = printer;
}
}
public class BasSqlService implements SqlService {
protected SqlReader sqlReader;
protected SqlRegistry sqlRegistry;
@Autowired // 생성자 주입
public BasSqlService(SqlReader sqlReader, SqlRegistry sqlRegistry) {
this.sqlReader = sqlReader;
this.sqlRegistry = sqlRegistry;
}
}
public class BasSqlService implements SqlService {
protected SqlReader sqlReader;
protected SqlRegistry sqlRegistry;
@Autowired // 일반 메소드를 이용한 주입
public void config(SqlReader sqlReader, SqlRegistry sqlRegistry) {
this.sqlReader = sqlReader;
this.sqlRegistry = sqlRegistry;
}
}
@Autowired // 컬렉션을 이용한 주입
Collection<Printer> printers; // Set, List로도 가능
@Autowired // 배열을 이용한 주입
Printer[] printers;
@Autowired // 맵을 이용한 주입
Map<String, Printer> printerMap; // String으로 된 빈 아이디가 키가 된다.
// 빈의 이름을 키로 하는 맵으로 DI 받을 수 있다. 빈의 이름이 필요한 경우에 유용하다.
- @Qualifier - 타입 외의 정보를 추가해서 자동와이어링을 세밀하게 제어할 수 있는 보조적인 방법, 타입에 의한 자동와이어링은 안전하고 편리하지만 타입만으로 원하는 빈을 지정하기 어려운 경우가 종종 발생한다.
<bean id="oracleDataSource" class="...AAADataSource">...</bean>
<bean id="mysqlDataSource" class="...BBBDatasource">...</bean>
// 둘이 다를때
@Resource("oracleDataSource") DataSource dataSource;
// 이 경우는 문제가 없다.
@Autowired DataSource dataSource;
// 이름이 다르지만, 같은 타입이 중복돼 오류가 날수도..
<bean id="oracleDataSource" class="...AAADataSource">
<qualfier value="mainDB"/>
</bean>
@Autowired
@Qualifier("mainDB")
DataSource dataSource;
@Component
@Qualifier("mainDB")
public class OracleDataSource {}
// Component로 자동스캔 시켜놓은 경우, 클래스에 Qualifier을 붙이면 된다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier // 아예 애노테이션을 만들어서 활용할 수도 있다.
public @interface Database {
String value();
}
@Autowired
@Database("main")
DataSource dataSource;
// 만든건 이렇게 활용도 할 수 있다.
@Autowired
@MainDB
DataSource dataSource;
// 더 간단하게 어노테이션 자체로 만들어 활용할 수도 있다.
@Autowired
public void config(@Qualifier("mainDB") DataSource dataSource, Printer printer) {}
// 파라미터에도 쓸 수 있다.
@Autowired(required=false) Printer printer;
// 빈을 혹시 못 찾아도 상관없다면, required false를 붙이면 된다.
@Autowired는 @Resource와 마찬가지로 지정하면 반드시 DI할 후보 빈이 존재해야 한다. 찾지 못해도 상관없다면 required를 통해 조절할 수 있다.
JavaEE 6의 표준인 JSR-330(DIJ)에는 @Autowired 및 @Qualifier과 비슷한 @Inject와 @Qualifier이 있다. 이름은 비슷하지만 패키지가 다르기 때문에 혼동하지 않도록 주의해야 한다. JSR-330 표준 애노테이션은 모두 javax.inject 패키지 내에 정의되어 있다.
- @Inject(javax.inject.Inject) - @Autowired와 매우 유사하지만 required 엘리먼트 같은 기능은 없다.
- @Qualifier(javax.inject.Qualifier) - 스프링의 Qualifier과 이름이 같지만 패키지가 다르고, 사용법도 다르다. 스프링의 @Qualifier는 스트링 값을 가질 수 있고 그 자체로 한정자로 @Autowired와 함께 사용할 수 있다. 반면에 JSR-330의 @Qualifier는 그 자체로는 한정자로 사용해서 @Inject와 함께 쓸 수 없다. 단지 다른 한정자 애노테이션을 정의하는 용도로만 사용 가능하다.
@Retention(RetentionPolicy.RUNTIME) // ?? 뭔지 잘 모름
@javax.inject.Qualifier
public @interface Main {}
// @Qualifier를 이용해 애노테이션을 만들 때는 엘리먼트를 추가해서 사용할 수도 있다.
JSR-330의 애노테이션은 스프링 외의 표준 JavaEE 6 환경에서도 같은 의미로 사용될 수 있기 떄문에 유용하다. 하지만 기능이 제한적이고 단순하기 떄문에 스프링에 독립적인 DI 설정을 가진 클래스를 만들 생각이 아니라면 스프링의 @Autowired와 @Qualifier를 사용하는 편이 낫다. 특별한 이유가 없다면 스프링과 JSR-330의 애노테이션을 함께 사용하는 방법은 권장되지 않는다.
@Autowired와 getBean(), 스프링 테스트
때로는 같은 타입이 여러 개 존재해서 @Qualifier를 쓰거나 어쩔 수 없이 @Resource를 사용해야 하지만 대개는 클래스나 인터페이스당 하나의 빈이 등록되므로 @Autowired만으로 충분하다.
getBean()은 기본적으로 Object 타입으로 리턴한다. 따라서 원하는 타입으로 캐스팅해야 하는데, 코드가 지저분하기 때문에 그보다는 제네릭 메소드를 이용해 타입 파라미터를 주는 다음과 같은 방법을 선호한다.
Printer printer = ac.getBean("myprinter", Printer.class);
Printer printer = ac.getBean(Printer.class);
// 특정 타입의 빈이 하나만 존재한다면. 두개 이상은 불가
@Autowired는 스프링 컨텍스트 테스트를 만들 때 이미 사용해봤다. 그때는 그저 "같은 타입의 빈이 테스트 컨텍스트에 존재하면 이를 테스트 메소드 실행 전에 필드에 넣어준다" 라고 설명했는데, 좀 더 정확히 말하자면 "테스트 클래스의 오브젝트에 애노테이션을 이용한 의존관계 설정을 해준다" 라고 할 수 있다. 따라서 @Qualifier를 포함해서 지금까지 설명한 모든 애노테이션 방식의 의존관계 설정 기법을 모두 적용할 수 있다. 그렇다고 해서 테스트 클래스가 애플리케이션 컨텍스트에 빈으로 등록되는 것은 아니다. 단지 컨텍스트의 빈 오브젝트를 테스트에서 손쉽게 사용할 수 있도록 테스트에 필요한 빈을 테스트 오브젝트의 필드에 넣어줄 뿐이다. 필드 외에 수정자와 일반 메소드를 이용할 수도 있다.
자바 코드에 의한 의존관계 설정
기본적으로 세 가지 방법을 사용할 수 있다.
- 애노테이션에 의한 설정 @Autowired, @Resource
public class Hello {
@Autowired Printer printer;
...
}
@Configuration
public class Config {
@Bean public Hello hello() {
return new Hello();
}
@Bean public Printer printer() {
return new Printer();
}
}
Hello 클래스의 printer필드에 @Autowired가 이미 부여되있다고 하더라도, @Autowired 같은 애노테이션을 통한 의존관계 설정은 빈 오브젝트 등록을 마친 후에 후처리기에 의해 별도의 작업으로 진행되기 때문이다. @Autowired 등을 사용했더라도 일부 프로퍼티는 코드에서 직접 의존관계를 지정해줄 수도 있다.
- @Bean메소드 호출
@Configuration과 @Bean을 사용하는 자바 코드 설정 방식의 기본은 메소드로 정의된 다른 빈을 메소드 호출을 통해 참조하는 것이다. @Bean이 붙은 메소드 자체가 하나의 빈 이름처럼 사용된다.
@Configuration
public class Config {
@Bean public Hello hello() {
Hello hello = new Hello();
hello.setPrinter(printer());
// printer() 메소드를 통해서 돌아온 오브젝트를 직접 수정자를 통해 DI한다.
// 일종의 수동 DI 방식이다.
return hello;
}
@Bean public Printer printer() {
return new Printer();
// @Configuration이 붙은 클래스는 스프링에서
// 여러 번 호출해도 매번 똑같은 오브젝트가 리턴한다.
}
}
@Configuration과 자바 코드를 이용한 설정 방식은 주의해서 다뤄야 한다. @Configuration이 붙지 않은 클래스의 @Bean 메소드에서는 이 바식을 사용하면 안 된다는 사실도 주의해야 한다.
- @Bean과 메소드 자동 와이어링
두 번째 방법의 단점을 극복하기 위해 사용할 수 있다. 메소드로 정의된 다른 빈을 가져와 자바 코드로 의존정보를 생성할 때 직접 @Bean이 붙은 메소드를 호출하는 대신 그 빈의 레퍼런스를 파라미터로 주입받는 방식을 사용하는 것이다.
@Configuration
public class Config {
@Bean public Hello hello(Printer printer) {
// 메소드로 지정한 빈을 파라미터로 지정하면 마치 @Autowired 한 것과 동일하게
// 파라미터로 Printer 타입의 빈 정보가 제공된다.
Hello hello = new Hello();
hello.setPrinter(printer);
return hello;
}
@Bean public Printer printer() {
return new Printer();
}
}
이 방법은 일반 @Autowired와 마찬가지로 @Qualifier를 파라미터에 추가해도 된다. 또, 한 개 이상의 파라미터를 사용할 수도 있다. 이렇게 제공되는 빈은 @Configuration이 붙은 클래스 안에서 정의되지 않아도 상관없다. XML이나 빈 스캐너를 이용해서 등록되는 빈을 가져와 자바 코드에 의해 만들어지는 빈에서 사용할 수도 있다.
Config클래스 내의 여러 @Bean 메소드에 참조되는 빈 오브젝트라면, 클래스 레벨의 DI를 통해 가져와도 된다. Config클래스에서 필드 주입이나 수정자 메소드 주입 등을 이용해 빈 오브젝트를 가져온 뒤 이를 각 @Bean메소드에서 공유해 사용하면 된다.
빈 의존관계 설정 전략
- XML 단독 - 빈 등록은 물론이고 의존관계 설정까지 모두 XML만으로 구성하는 방법이다. 순수한 자바 코드에 환경에 대한 일체의 정보도 허용하기를 원치 않는 순수주의자라면 전통적인 XML 방식을 고집할 수 있을 것이다.
- XML과 애노테이션 설정의 혼합 - 빈은 XML로 등록하지만 의존관계 정보는 @Autowired나 @Resource 같은 애노테이션을 이용하는 방법도 자주 사용된다.
- 애노테이션 단독 - 빈의 등록도 @Component 애노테이션을 이용해 스캐너에게 맡기고 의존관계 역시 @Autowired와 같은 애노테이션을 이용해 자동으로 등록하는 방법이다. 빈을 등록하는데 XML이 필요 없기 때문에 생산성이 높고 수정이 편리하다는 장점이 있어서 점차 비중이 늘어가고 있는 방식이다. 물론 이때도 일부 기술 서비스 빈이나 컨테이너 설정용 빈은 XML을 이용할 수 있다. 스키마와 전용 태그를 사용하기 때문에 얻을 수 있는 장점이 많기 때문이다. XML이 하나도 없는 순수한 애노테이션만의 설정을 원한다면 일부 기술 서비스 빈은 @Configuration 자바 코드를 이용해 등록해줘야 한다.
프로퍼티 값 설정 방법
메타 정보 종류에 따른 값 설정 방법
- XML
<property> 의 value를 이용해 넣을 수 있다. String이라면 간단히 넣을 수 있지만 int, float, double, boolean같은 기본 타입이거나 Class나 Resource같은 경우는 value 애트리뷰트로 바로 넣을 수 없지만 적절한 변환이 필요하다.
- @Value 애노테이션
public class Hello {
private String name = "Everyone";
public void setName(String name) {
this.name = name;
}
} // 디폴트 값 사용 예
public class Hello {
private String name;
@Value("Everyone")
public void setName(String name) {
this.name = name;
}
} // @Value를 이용한 값 주입
@Value("${database.username}") // 프로퍼티에서 값을 주입하는 경우
String username;
// 자바 코드 설정에 사용하는 경우
@Confiuration
public class Config {
@Value("${database.username}")
private String name;
@Bean
public Hello hello() {
Hello hello = new Hello();
hello.setName(this.name);
return hello;
}
@Bean // 파라미터에서 사용할 수도 있다.
public Hello hello(@Value("${database.username}") String name) {
Hello hello = new Hello();
hello.setName(name);
return hello;
}
}
PropertyEditor와 ConversionService
XML의 value 어트리뷰트나 @Value의 엘리먼트는 모두 텍스트 문자로 작성된다. 값을 넣을 프로퍼티 타입이 스트링이라면 상관없지만, 그 외의 타입인 경우라면 타입을 변경하는 과정이 필요하다. 이를 위해 스프링은 두가지 종류의 타입 변환 서비스를 제공한다. 디폴트로 사용되는 변환기는 PropertyEditor라는 java.beans의 인터페이스를 구현한 것이다. 스프링은 프로퍼티 에디터 개념을 XML 또는 @Value의 스트링 값에서 빈 오브젝트의 프로퍼티 타입으로 변경하는 데 활용한다. 기본적으로 지원하는 변환 가능한 타입을 보자.
- 기본 타입 - boolean, Boolean, byte, Byte, short, Short, int, Integer, long, Long, float, Float, double, Double, BigDecimal, BigInteger, char, Character, String
boolean flag;
public void setFlag(boolean flag) { this.flag = flag; }
<property name="flag" value="true"/> // use XML
@Value("1.2") double rate;
// @Value, value는 기본적으로 둘다 String으로 만들어야한다.
- 배열 - byte[], char[], short[], int[], long[]
@Value("1, 2, 3, 4") int[] intarr; // 배열로 넣어준다.
- 기타 - 이 외에도 스프링은 Charset, Class, Currency, File, InputStream, Locale, Pattern, Resource, Timezone, URI, URL의 타입을 지원해준다.
문자열로 각 타입의 값을 어떻게 나타낼 수 있는지는 각 프로퍼티 에디터의 API 문서를 참조하면 된다. 각 타입의 프로퍼티 에디터를 찾는 방법은 간단하다. 타입 이름뒤에 Editor를 붙여주면 된다. 스프링 API문서에서 CharsetEditor를 찾으면 방법을 알 수 있다. 스프링이 지원하지 않는 타입의 오브젝트를 직접 값으로 주입하고 싶다면, PropertyEditor 인터페이스를 구현해 직접 변환기를 만들어 사용할 수 있다. 하지만 권장하지 않는다.
ConversionService는 자바빈에서 차용해서 사용해오던 PropertyEditor와 달리 스프링이 직접 제공하는 타입 변환 API다. PropertyEditor와 달리 멀티스레드 환경에서 공유해 사용될 수 있다.
<bean id="conversionService" class="org ... ConversionServiceFactoryBean">
// conversionService라는 이름의 빈으로 ConversionService 타입의 빈을 등록하면
// 컨베이스가 자동 인식해서 PropertyEditor를 대신해서 사용한다.
<property name="conveters>
<list>
<bean class="springbook.conveter.MyTypeConverter />
// 직접 정의한 타입 변환기를 등록할 수 있다.
// 기본적으로 등록된 변환 타입에 추가돼서 value, @Value의 값을 변환하는데 사용한다.
</list>
</property>
</bean>
컬렉션
컬렉션 타입을 지정하려면 어떻게 해야할까?
- List, Set
List<String> names; // 혹은 Set
<property name="names">
<list>
<value>Spring</value>
<value>IOC</value>
<value>DI</value>
</list>
</property>
- Map
Map<String, Integer> ages;
<property name="ages">
<map>
<entry key="Kim" value="30"/>
<entry key="Lee" value="35"/>
<entry key="Ahn" value="40"/>
</map>
</property>
- Properties
Properties settings;
<property name="settings">
<props>
<prop key="username">Spring</prop>
<prop key="password>Book</prop>
</props>
</property>
// 다른 빈의 레퍼런스에 대한 컬렉션도 정의할 수 있다.
<property name="beans">
<list>
<ref bean="beanA" />
<ref bean="beanB" />
</list>
</property>
- <util:list>, <util:set> List, Set을 빈으로 선언하도록 해준다.
<util:list id="names"> // 혹은 <util:set>
<value>Spring</value>
<value>IOC</value>
<value>DI</value>
</util:list>
<util:list id="names" list-class="java.util.LinkedList">
// 어떤 List 클래스를 구현할지도 지정할 수 있다.
- <util:map>
<util map id="ages" map-class="java.util.TreeMap">
<entry key="Kim" value="30"/>
<entry key="Lee" value="35"/>
<entry key="Ahn" value="40"/>
</util>
- <util:properties>
<util:properties id="setting">
<prop key="username">Spring</prop>
<prop key="password">Book</prop>
</util:properties>
// XML에 직접 등록하는 대신 외부의 프로퍼티 파일을 지정해서 그 내용을 사용할 수 있다.
<util:properties id="setting" location="classpath:settings.properties" />
'Spring > 개념' 카테고리의 다른 글
Maven scope (0) | 2022.06.20 |
---|---|
[토비의 스프링] AOP 용어 (0) | 2022.06.02 |
[토비의 스프링1] 서비스 추상화 (0) | 2022.05.12 |
디자인 패턴 정리 (0) | 2022.04.27 |
[Spring] MVC 패턴에서의 5가지 계층에 대한 정보 (0) | 2021.08.21 |