지금까지는 스프링을 사용하지 않고 의존성을 주입했다. 이제 스프링을 이용해 의존성을 주입해보자.
의사 코드
운전자가 종합 쇼핑몰에서 타이어를 구매했다.
운전자가 종합 쇼핑몰에서 자동차를 구매했다.
운전자가 자동차에 타이어를 장착했다.
자바로 표현 - 속성 메서드 사용
ApplicationContext context = new ClassPathXmlApplicationContext("expert002.xml", Driver.class);
Tire tire = (Tire)context.getBean("tire");
Car car = (Car)context.getBean("car");
car.setTire(tire);
스프링을 통한 의존성 주입은 생성자
를 통한 의존성 주입과 속성
을 통한 의존성 주입을 모두 지원하는데, 여기서는 속성을 통한 의존성 주입만 살펴보자.
위의 의사코드를 보면 생산에서 구매로 달라졌을 뿐 나머지는 바뀌지 않았다. 스프링을 도입한다고 해서 기존 방식과 달라질 것은 없다. 또한 그동안 작성해온 Tire 관련 클래스와 Car 클래스 역시 달라지는 부분이 전혀 없도록 코딩할 수 있다. 오직 Driver 클래스만 살짝 손봐주고 스프링 설정 파일 하나만 추가하면 작업이 끝난다.
위는 스프링 프레임워크를 도입한 후의 시퀀스 다이어그램이고 아래는 기존의 시퀀스 다이어그램이다. 기존 다이어그램과 비교해서 달라진 곳이 있는지 살펴보자. 종합 쇼핑몰이 하나 들어온 것 외에는 달라진 부분이 없다. 운전자가 타이어, 자동차를 직접 생산하던 시스템에서 종합 쇼핑몰을 통해 구매하는 형태로 바뀌었다. 즉, 현실 세계와 더욱 유사해졌다.
종합 쇼핑몰 스프링 프레임워크가 들어오면서 달라지는 코드를 살펴보자.
Driver.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Driver {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("expert002/expert002.xml");
Car car = context.getBean("car", Car.class);
Tire tire = contet.getBean("tire", Tire.class);
car.setTire(tire);
System.out.println(car.getTireBrand());
}
}
우선 2개의 import 문이 추가된 것을 볼 수 있다.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
종합 쇼핑몰(스프링 프레임워크)에 대한 정보를 가지고 있는 패키지라고 기억해두자. 그리고 종합 쇼핑몰에 대한 정보가 필요하다. 자바 코드는 아래와 같다.
ApplicationContext context = new ClassPathXmlApplicationContext("expert002/expert002.xml");
드디어 종합 쇼핑몰에서 상품에 해당하는 Car와 Tire를 구매하는 코드다.
Car car = context.getBean("car", Car.class);
Tire tire = context.getBean("tire", Tire.class);
그리고 한 가지 더 필요한 것이 있다. 아무리 종합 쇼핑몰이라고는 하지만 상품이 입점돼 있어야만 판매할 수 있을 것이다. 입점된 상품에 대한 정보는 어디에 숨어 있을까? 바로 위 코드에서 XML 파일이 하나 보이는데 전체 경로는 아래와 같다.
/src/main/java/expert002/expert002.xml
expert002.xml 파일을 살펴보자. 이 XML 파일 안에 쇼핑몰에서 구매 가능한 상품 목록이 등록돼 있어야 한다. 상품 목록이 담긴 XML 파일을 만들려면 expert002 패키지에서 마우스 오른쪽 버튼을 클릭한 후 New -> Other -> Spring -> Spring Bean Configuration File을 차례대로 선택하고 이름만 지정하면 된다.
종합 쇼핑몰 판매 목록을 등록하기 위한 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">
</beans>
이름을 expert002.xml로 지정하고 나면 위와 같은 XML 파일이 만들어진다. 이렇게 생성된 XML 파일에 쇼핑몰에서 판매하는 상품 목록을 등록하면 된다. 이제 상품을 등록해보자.
종합 쇼핑몰 판매 목록을 등록하기 위한 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="tire" class="expert002.KoreaTire"></bean>
<bean id="americaTire" class="expert002.AmericaTire"></bean>
<bean id="car" class="expert002.Car"></bean>
</beans>
위의 예제에서는 3개의 상품을 등록했다. 상품을 등록할 때는 bean 태그
를 이용해 등록한다. 이때 각 상품을 구분하기 위한 id 속성과 그 상품을 어떤 클래스를 통해 생산(인스턴스화)해야 할지 나타내는 class 속성을 함께 지정하면 된다.
KoreaTire.java가 XML 파일에서 id=tire인 bean 태그와 연결돼 있고, 다시 Driver.java의 main() 메서드 안의 코드인 context.getBean("tire", Tire.class)와 연결돼 있는 것을 볼 수 있다. 이 과정을 현실 세계의 예로 풀어보자.
"KoreaTire라고 하는 상품이 tire라는 이름으로 진열돼 있고, 구매(getBean)할 수 있다."
스프링을 도입해서 얻는 이득은 무엇일까? 가장 큰 이득을 꼽으라면 자동차의 타이어 브랜드를 변경할 때 그 무엇도 재컴파일/재배포하지 않아도 XML 파일만 수정하면 프로그램의 실행 결과를 바꿀 수 있다는 것이다.
Driver.java의 Tire tire = context.getBean("tire", Tire.class); 부분이 타이어를 구매하는 부분인데, 자바 코드 어디에서도 KoreaTire 클래스나 AmericaTire를 지칭하는 부분이 없다. 바로 expert002.xml 파일에 이에 해당하는 내용이 있기 때문이다. 지금은 expert002.xml에서 id가 tire인 bean 태그의 class 어트리뷰트가 KoreaTire로 지정돼 있는데
<bean id="tire" class="expert002.KoreaTire"></bean>
<bean id="americatire" class="expert002.AmericaTire"></bean>
AmericaTire로 타이어를 바꿔야 하더라도 자바 코드를 변경/재컴파일/재배포할 필요가 없다. XML 파일을 변경하고 프로그램을 실행하면 바로 변경사항이 적용된다.
<bean id="KoreaTire" class="expert002.KoreaTire"></bean>
<bean id="tire" class="expert002.AmericaTire"></bean>
위와 같이 expert002.xml 파일을 고치고 Driver.java에 마우스 오른쪽 버튼을 클릭한 후 Run As -> Java Application을 선택해 프로그램을 실행해보자. 결과가 미국 타이어로 나오는 것을 확인할 수 있다.
의사 코드 - 점점 더 현실 세계를 닮아가고 있다.
운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다.
종합 쇼핑몰은 자동차를 생산한다.
종합 쇼핑몰은 타이어를 생성한다.
종합 쇼핑몰은 자동차에 타이어를 장착한다.
종합 쇼핑몰은 운전자에게 자동차를 전달한다.
자바로 표현
ApplicationContext context = new ClassPathXmlApplicationContext("expert003.xml", Driver.class);
Car car = (Car)context.getBean("car");
XML로 표현
<bean id="tire" class="expert003.KoreaTire"></bean>
<bean id="Americatire" class="expert003.AmericaTire"></bean>
<bean id="car" class="expert003.Car"></bean>
<property name="tire"> ref="KoreaTire"></property>
</bean>
XML 파일에 새롭게 property라고 하는 부분이 보인다. 자바에서 접근자 및 설정자 메서드를 속성 메서드라고 하는데 영어로 속성은 Property다. 결국 Driver.java에서 car.setTire(tire)라고 하던 부분은 XML 파일의 property 태그를 이용해 대체하는 것이다.
Tire.java, KoreaTire.java, AmericaTire.java, Car.java는 바뀌는 부분이 없다. 변화가 있는 2개의 파일만 살펴보자.
Driver.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Driver {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("expert003/expert003.xml");
Car car = context.getBean("car", Car.class);
System.out.println(car.getTireBrand());
}
}
이전의 코드와 달리 삭제된 두 줄이 있다.
Tire tire = contet.getBean("tire", Tire.class);
car.setTire(tire);
사라진 두 줄은 어떻게 된 것일까? XML 파일을 살펴보면 사라진 이유를 알 수 있다.
expert003.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="koreaTire" class="expert003.KoreaTire"></bean>
<bean id="americaTire" class="expert003.AmericaTire"></bean>
<bean id="car" class="expert002.Car">
<property name="tire" ref="KoreaTire"></property>
</bean>
</beans>
참고