XML 기반 Bean 설정
Spring 프레임워크에서는 XML 파일을 사용하여 Bean을 구성할 수 있습니다. 먼저 리소스 디렉토리에 XML 파일을 생성하고, 사전에 Spring Context 의존성을 프로젝트에 추가해야 합니다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
XML 파일에서 Bean 설정
<?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">
<bean id="memberServiceImpl" class="com.example.service.impl.MemberServiceImpl"></bean>
</beans>
설정 완료 후 Java 클래스에서 Bean을 가져오는 방법은 다음과 같습니다:
public static void main(String[] args) {
// IOC 컨테이너 생성
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// Bean 가져오기
MemberService memberService = (MemberService) context.getBean("memberServiceImpl");
}
Bean 별칭 설정
name 속성을 활용하면 하나의 Bean에 여러 별칭을 부여할 수 있습니다.
정적 팩토리를 이용한 Bean 생성
정적 팩토리 클래스를 먼저 구현합니다:
public class ProductDaoFactory {
public static ProductDao getProductDao() {
return new ProductDaoImpl();
}
}
XML 설정 파일에서 해당 정적 팩토리 메서드를 참조합니다:
<bean
id="productDao"
factory-method="getProductDao"
class="com.example.factory.ProductDaoFactory"/>
FactoryBean 인터페이스를 통한 Bean 생성
public class ArticleDaoFactoryBean implements FactoryBean<ArticleDao> {
@Override
public ArticleDao getObject() throws Exception {
return new ArticleDaoImpl();
}
@Override
public Class<?> getObjectType() {
return ArticleDao.class;
}
}
XML 설정:
<bean id="articleDao" class="com.example.factory.ArticleDaoFactoryBean"/>
Bean 라이프사이클
컨테이너 초기화 단계:
- 객체 생성(메모리 할당)
- 생성자 실행
- 속성 주입(setter 수행)
- Bean 초기화 메서드 실행
Bean 사용 단계:
비즈니스 로직 수행
컨테이너 종료 단계:
- Bean 소멸 메서드 실행
Bean 소멸 시점
컨테이너가 닫히기 전에 Bean의 소멸 메서드가 실행됩니다. 컨테이너 종료 방법은 두 가지가 있습니다:
- ConfigurableApplicationContext 인터페이스의 close() 메서드 호출
- registerShutdownHook() 메서드를 사용하여 VM 종료 전에 컨테이너를 먼저 종료
의존성 주입 방식
Setter 주입
단순 타입과 참조 타입을 모두 지원합니다. 먼저 엔티티 클래스에서 setter 메서드를 정의합니다:
public class BoardDaoImpl implements BoardDao {
private int connectionTimeout;
public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
}
XML 설정 파일에서 property 요소를 사용하여 값을 지정합니다:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<property name="connectionTimeout" value="300"/>
</bean>
생성자 주입
단순 타입과 참조 타입 모두 동일하게 적용됩니다.
public class BoardDaoImpl implements BoardDao {
private String databaseName;
private int maxConnections;
public BoardDaoImpl(String databaseName, int maxConnections) {
this.databaseName = databaseName;
this.maxConnections = maxConnections;
}
}
XML 설정:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<constructor-arg name="databaseName" value="oracle"/>
<constructor-arg name="maxConnections" value="50"/>
</bean>
파라미터 이름 대신 타입으로 지정하여 결합도를 낮출 수 있습니다:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<constructor-arg type="java.lang.String" value="oracle"/>
<constructor-arg type="int" value="50"/>
</bean>
동일한 타입의 파라미터가 여러 개인 경우 인덱스로 구분합니다:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<constructor-arg index="0" value="oracle"/>
<constructor-arg index="1" value="50"/>
</bean>
자동 주입
XML 파일을 통해 자동 주입을 설정할 수 있습니다:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl"/>
<bean id="boardService" class="com.example.service.impl.BoardServiceImpl" autowire="byType"/>
autowire 속성을 사용하여 타입 기반으로 주입합니다.
자동 주입 특성
- 참조 타입의 의존성 주입에만 사용되며 단순 타입에는 적용 불가
- byType 방식 사용 시 해당 타입의 Bean이 유일해야 함(권장 방법)
- byname 방식은 변수명과 설정이 결합되어 있어 권장하지 않음
- 자동 주입 우선순위는 setter 주입과 생성자 주입보다 낮음
컬렉션 주입
엔티티 클래스에서 컬렉션 타입의 의존성을 선언합니다:
public class BoardDaoImpl implements BoardDao {
private int[] numbers;
private List<String> categories;
private Map<String, String> config;
private Properties settings;
public void setNumbers(int[] numbers) {
this.numbers = numbers;
}
}
XML에서 배열 설정:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<property name="numbers">
<array>
<value>10</value>
<value>20</value>
</array>
</property>
</bean>
List 컬렉션 설정:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<property name="categories">
<list>
<value>notice</value>
<value>free</value>
</list>
</property>
</bean>
Map 컬렉션 설정:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<property name="config">
<map>
<entry key="db" value="mysql"/>
</map>
</property>
</bean>
Properties 설정:
<bean id="boardDao" class="com.example.dao.impl.BoardDaoImpl">
<property name="settings">
<props>
<prop key="author">admin</prop>
</props>
</property>
</bean>
외부 Properties 파일 로딩
Spring에서 외부 properties 파일을 로드하려면 XML에 새로운 네임스페이스를 추가해야 합니다:
<?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
http://www.springframework.org/schema/context/spring-context.xsd">
properties 파일 로딩:
<context:property-placeholder location="classpath:database.properties"/>
파일 내 속성 사용:
<bean class="com.example.config.DatabaseConfig">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
</bean>
여러 properties 파일 로딩:
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
system-properties-mode 속성은 시스템 속성 로딩 여부를 지정합니다.
컨테이너 클래스 계층 구조
BeanFactory가 생성된 후에는 모든 Bean이 지연 로드됩니다.