
우리는 Spring IoC Container에게 객체(Bean)를 어떤 방식으로 만드는지에 관한 정보를 전달해줘야 한다. 이 때, POJO와 Configuration Metadata를 전달해주는데 이 Configuration Metadata를 전달하는 방법에는 3가지 방법이 있다. 오늘은 이에 관해 알아 볼 것이다.

package com.dbwls.common;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@AllArgsConstructor
public class MemberDTO {
private int sequence; //회원번호
private String id; //아이디
private String pwd; //비밀번호
private String name; //이름
}
⚙️태그 내용
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id는 bean의 식별자이고, class에서 이 Bean이 어떤 클래스로 생성될지 정의 -->
<bean id="member" class="com.dbwls.common.MemberDTO" >
<!-- index로 지정해도 되고, name을 통해서 지정해도 된다. -->
<!-- 생성자를 호출할 때 전달할 인자를 정의
아무것도 작성하지 않으면 기본 생성자를 사용한다는 의미-->
<constructor-arg index="0" value="1"/>
<constructor-arg name="id" value="user01"/>
<constructor-arg index="2"><value>pass01</value></constructor-arg>
<constructor-arg name="name"><value>홍길동</value></constructor-arg>
</bean>
</beans>
⚙️ GenericXmlApplicationContext : 구현 클래스
XML 설정 메타 정보를 전달하기 때문에, GenericXmlApplicationContext이라는 클래스를 이용해 ApplicationContext(이게 IoC Container)를 생성한다.
import com.dbwls.common.MemberDTO;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
public static void main(String[] args) {
/* GenericXmlApplicationContext 클래스를 이용해 ApplicationContext를 생성한다.
* 생성자에 XML 설정 메타 정보를 인자로 전달한다. */
ApplicationContext applicationContext =
new GenericXmlApplicationContext("section01/xmlconfig/spring-context.xml");
// 여기에서 핵심은 우리가 직접 memberDTO 객체를 생성하지 않은 것!
// 1. Bean의 이름을 통해서 가져옴
// MemberDTO member = (MemberDTO)applicationContext.getBean("member");
// 2. Bean의 타입을 통해서 가져옴
// MemberDTO member = applicationContext.getBean(MemberDTO.class);
// 3. Bean의 이름과 타입을 통해 가져옴
// MemberDTO 타입이 여러 개가 있다면 이렇게 2가지를 전달해서 사용하면 됨
MemberDTO member = applicationContext.getBean("member",MemberDTO.class);
System.out.println(member);
}
}
MemberDTO라는 POJO 클래스를 만들었다. 이 클래스는 데이터만을 담는 객체로, 어떤 패턴이나 상속, 구현이 없는 순수한 클래스라고 생각하면 된다.MemberDTO 클래스를 Spring 컨테이너에 등록하기 위해 Bean 정의를 작성한다.class="com.dbwls.common.MemberDTO"로 MemberDTO 클래스가 Bean의 타입으로 지정되어 있다.constructor-arg를 통해 MemberDTO 객체가 생성될 때 필요한 인자값들을 전달했다. 예를 들어, index="0" value="1"은 MemberDTO 생성자의 첫 번째 인자로 1을 전달하는 것이고, name="id" value="user01"은 id라는 이름의 인자에 user01 값을 전달하는 방식이다.
@Bean을 이용해 getMember() 메소드의 반환값을 spring Bean으로 등록한다.
import com.dbwls.common.MemberDTO;
import org.springframework.context.annotation.Bean;
public class ConfigurationContext1 {
/* @Bean 사용 시 name 속성을 생략하면 메소드명이 bean 이름이 된다.
* 만약 이것을 원치 않는다면, name 속성을 적어주면 된다. */
@Bean(name = "member")
public MemberDTO getMember(){
return new MemberDTO(1,"user01","pass01", "홍길동");
}
}
⚙️ AnnotationConfigApplicationContext : 구현 클래스
Java 코드를 이용해 설정 메타 정보를 전달하기 때문에, AnnotationConfigApplicationContext이라는 클래스를 이용해 ApplicationContext(이게 IoC Container)를 생성한다.
import com.dbwls.common.MemberDTO;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
// 1. ApplicationContext 생성하기
ApplicationContext applicationContext
= new AnnotationConfigApplicationContext(ConfigurationContext1.class);
// 2. member라는 name의 bean을 가져오기
MemberDTO member = applicationContext.getBean("member", MemberDTO.class);
System.out.println(member);
}
}
ConfigurationContext1 클래스를 로드한다.@Bean이 붙은 메서드가 있는지 확인한다.getMember() 메서드를 실행하여 MemberDTO 객체를 생성한다.new MemberDTO(1, "user01", "pass01", "홍길동")을 호출하여 객체를 생성한다."member"라는 이름으로 저장한다.@Bean(name = "member")에 의해 해당 객체가 "member"라는 이름의 Bean으로 등록된다.ApplicationContext에서 "member" Bean을 가져와 사용한다.getBean("member", MemberDTO.class)을 호출하면 Spring 컨테이너에서 저장된 MemberDTO 객체를 반환한다.
@Component라는 annotation이 붙어 있다면, 이걸 스캔해서 bean으로 등록한다.<bean>태그와 동일한 역할이다.
: 이 클래스가 스캔되어 Bean 객체로 등록
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
// Component라는 어노테이션이 등록되어,
// 이 클래스가 스캔되어 빈 객체로 등록되는 것이다.
@Component
public class MemberDAO {
private final Map<Integer, MemberDTO> memberMap;
public MemberDAO() {
memberMap = new HashMap<>();
memberMap.put(1, new MemberDTO(1, "user01", "pass01", "홍길동"));
memberMap.put(2, new MemberDTO(2, "user02", "pass02", "유관순"));
}
/* 매개변수로 전달 받은 회원 번호를 map에서 조회 후 회원 정보를 리턴하는 메소드 */
public MemberDTO selectMember(int sequence) {
return memberMap.get(sequence);
}
/* 매개변수를 전달 받은 회원 정보를 map에 추가하고 성공 실패 여부를 boolean으로 리턴하는 메소드 */
public boolean insertMember(MemberDTO newMember) {
int before = memberMap.size();
memberMap.put(newMember.getSequence(), newMember);
int after = memberMap.size();
return after > before;
}
}
@Configuration("configurationContextJava")
: 이 annotation을 통해 이 파일이 componetMetadata라는 것을 알려줌
@ComponentScan(basePackages = "com.dbwls")
: com.dbwls 패키지 아래에 있는 컴포넌트(Bean)들을 자동으로 검색해서 스프링 컨테이너에 등록하라는 의미
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/* @Configuration
: @Component의 구체화 어노테이션으로 설정 정보를 담는 클래스로
여기에 정의된 내용을 기반으로 Bean을 등록 */
@Configuration("configurationContextJava")
/* @ComponentScan : Componenet Scan과 관련된 설정을 기입하며, basePackages를 기입하지 않으면
* default는 현재 패키지 기준으로 Scan이 수행 된다. */
@ComponentScan(basePackages = "com.dbwls")
public class ConfigurationContext {
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext
= new AnnotationConfigApplicationContext(ConfigurationContext.class);
String[] beanNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanNames){
System.out.println("beanName : " + beanName);
}
}
}
⚙️context:component-scan
위에서 알아본 @ComponentScan(basePackages = "com.dbwls")와 같은 역할이다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- component를 스캔해라!-->
<context:component-scan base-package = "com.dbwls"/>
</beans>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext applicationContext
= new GenericXmlApplicationContext("section03/xmlconfig/spring-context.xml");
String[] beanNames = applicationContext.getBeanDefinitionNames();
for(String beanName : beanNames){
System.out.println("beanName : " + beanName);
}
}
}
지금까지 ConfigurationMetadata를 보내는 방식을 배웠다. 그렇다면 이 각각의 방법을 언제 어떤 상황에 사용하면 될까?