본문 바로가기
Spring&SpringBoot/<토비의 스프링 3.1 Vol1.1>, 이일민

applicationContext.xml로 객체 관계 설정하기

by 민휘 2023. 3. 2.

스프링은 빈의 생성과 관리를 담당한다. 개발자는 객체의 관계를 설정하는 책임만 가지면 된다. 이때 객체 관계를 설정하는 방법은 여러가지가 있다. 자바 클래스를 사용해도 되지만, 보다 간편한 xml 파일로 관계 설정 정보를 작성하는 것이 일반적이다. 이 예제에서는 자바 클래스로 작성된 객체 관계를 xml 파일로 변경해본다. (하지만 스프링 mvc를 사용하는 요즘.. 다 애노테이션 쓰지 xml은 안 쓴다)

 

다음과 같이 자바 클래스로 작성된 객체 관계를 xml 파일로 변경해보자.

@Configuration
public class DaoFactory {
    @Bean
    public UserDao userDao() {
        UserDao userDao = new UserDao();
				userDao.setConnectionMaker(connectionMaker()); // 수정자 주입
				return userDao;
    }

    @Bean
    public ConnectionMaker connectionMaker() {
        return new NConnectionMaker();
    }
}

 

수정자 주입 매핑하기

빈 목록을 정의하는 <beans>를 루트로 하여 <bean> 태그로 빈의 관계 정보를 작성한다.

클래스와 xml은 다음과 같이 매핑된다.

  • 빈 이름 : 메소드 이름 → id
  • 주입되는 구현체 : 리턴 객체 → class
  • 수정자 의존관계 설정 : setter → <property name=”” ref=””> (name은 수정자의 프로퍼티, ref는 주입되는 빈 id)

 

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="connectionMaker" class="springbook.user.dao.NConnectionMaker" />

    <bean id="userDao" class="springbook.user.dao.UserDao">
        <property name="connectionMaker" ref = "connectionMaker" />
    </bean>

</beans>

그리고 애플리케이션 컨텍스트에서 빈을 받아오는 테스트 코드는 다음과 같이 변경한다.

ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

 

 

생성자 주입 매핑하기

UserDao의 의존성 주입 방식으로 생성자 주입을 추가로 제공해보자. 생성자 주입은 수정자 주입보다 의존성을 명시적으로 드러내기 때문에 더 좋은 의존성 관리 방식이다. UserDao의 클래스에 다음과 같은 생성자를 추가한다.

public UserDao(ConnectionMaker connectionMaker) {
	this.connectionMaker = connectionMaker;
}

 

그러면 Ide가 applicationContext.xml 파일의 userDao 빈에 빨간 줄을 그어준다. 메시지를 확인해보면 <constructor-arg>를 추가하라고 한다. 생성자로 의존관계를 주입할 때는 xml에 해당 태그를 추가해주어야 한다. 수정자 주입을 매핑하기 위해 <property>를 사용했던 것처럼 말이다.

<bean id="userDao" class="springbook.user.dao.UserDao">
	<constructor-arg ref="connectionMaker"/>
	<property name="connectionMaker" ref="connectionMaker" />
</bean>

 

프로퍼티 값 주입

위에서 살펴보았듯이 수정자 주입으로 구체적인 클래스를 넘겨줄 수 있다. 이때 넘겨지는 의존성 또한 스프링 빈이기 때문에 xml로 매핑할 때 빈의 id를 넘겨주면 된다. 그러나 때로는 수정자로 문자열이나 클래스를 설정해주어야 하는 경우도 있다. 이럴 때는 <property> 태그에 ref 속성 대신 value 속성을 넘겨주면 된다.

 

우리가 임의로 만든 ConnectionMaker 대신 자바가 제공하는 DataSource 인터페이스를 사용하자. jdbc 라이브러리를 추가하고 UserDao가 ConnectionMaker 대신 DataSource를 사용하도록 바꾼다. UserDao는 수정자 주입을 사용하고 있다.

public class UserDao {

    DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void add(User user) throws ClassNotFoundException, SQLException {
        Connection c = dataSource.getConnection();
				// ...

 

위의 의존성을 자바 클래스로 표현하면 다음과 같다. 새로 추가한 DataSource의 구현체로 SimpleDriverDataSource를 선택했다. 구현체 생성 후에 세터로 프로퍼티의 값을 주입하고 있다. 이런 경우는 어떻게 xml로 매핑할 수 있을까? property 태그에 value 속성을 넘겨주면 된다.

@Configuration
public class DaoFactory {
    @Bean
    public UserDao userDao() {
        UserDao userDao = new UserDao();
        userDao.setDataSource(dataSource());
        return userDao;
    }

    @Bean
    public DataSource dataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource ();

        dataSource.setDriverClass(com.mysql.jdbc.Driver.class);
        dataSource.setUrl("jdbc:mysql://localhost/springbook?characterEncoding=UTF-8");
        dataSource.setUsername("spring");
        dataSource.setPassword("book");

        return dataSource;
    }
}

 

프로퍼티의 값을 주입하는 경우는 어떻게 xml로 매핑할 수 있을까? property 태그에 value 속성을 넘겨주면 된다.

<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
	<property name="driverClass" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost/toby?characterEncoding=UTF-8"/>
	<property name="username" value="root"/>
	<property name="password" value="비번"/>
</bean>

정말 신기하게도 클래스의 경로를 문자열로 넘겨주었는데도 클래스가 프로퍼티 값으로 세팅되었다. 스프링이 프로퍼티의 값을 수정자 메소드의 파라미터 타입을 참고해서 적절한 형태로 변환해준다. 스프링 짱 🥹