목표
public class GridExamConsole implements ExamConsole {
private Exam exam;
public GridExamConsole() {
}
public GridExamConsole(Exam exam) {
this.exam = exam;
}
@Override
public void setExam(Exam exam) {
this.exam=exam;
}
}
위 코드에서 볼 수 있듯이, Exam 클래스는 GridExamConsole이라는 클래스에 종속되어 있다.
이 때, Spring을 쓰지 않았을 경우와 썻을 경우 어떻게 DI를 수행하는지 살펴보자.
그리고 IoC 컨테이너에서 DI한 객체를 사용해보자.
Spring을 쓰지 않은 DI 방식
public class Program {
public static void main(String[] args) {
Exam exam = new NewlecExam();
ExamConsole console = new GridExamConsole();
console.setExam(exam); // Dependency Injection
}
}
Spring을 쓰지않고 setter를 통해 DI한 모습이다.
Spring xml을 쓰고 DI하는 방식
<!-- setting.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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="exam" class="spring.di.entity.NewLecExam"/>
<bean id="console" class="spring.di.ui.GridExamConsole">
<property name="exam" ref="exam"/>
</bean>
<beans>
먼저 작은 부품인 exam을 생성하고, 큰 부품인 console을 생성한다.
그런데 exam은 console에 종속되어 있으며 Injection이 필요한 상태이다.
따라서 property라는 태그를 사용하여 IoC 컨테이너에 추가했었던 exam 객체를 주입해준다.
여기서 property 내부의 name 속성에 exam은 setExam 메소드를 의미하는 것으로, setter 주입을 의미한다. 만약 GrideExamConsole 클래스에 setter를 생성해주지 않았다면 에러가 발생한다.
(반드시 property의 name에는 setExam 메소드에서 set 빼고 대문자를 소문자로 치환한 exam으로 작성해야한다.)
그리고 exam은 reference 객체이므로property에서 ref="exam"을 통해 객체를 가져와 setter의 매개변수로 사용된다.
스프링 IoC 컨테이너 사용하기
public class Program {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/di/setting.xml");
ExamConsole console = (ExamConsole) context.getBean("console");
//ExamConsole console = context.getBean(ExamConsole.class);
console.print();
}
}
context는 Ioc 컨테이너의 이름으로, ClassPathXmlApplicationContext 생성자를 통해 생성됐다.
해당 IoC 컨테이너에서 getBean 메소드를 통해 위 xml 파일에 DI 했었던 console 이라는 id를 가진 객체를 가져올 수 있다.
이 객체는 오브젝트 형식으로 반환되기 떄문에, 반드시 앞에 사용할 타입을 명시해줘야한다.
getBean은 id명을 가져오거나, 위 주석처리된 것처럼 클래스의 이름으로도 가져올 수 있다.
하지만 위의 ExamConsole 클래스는 인터페이스로, InnerExamConsole과 GridExamConsole라는 2개의 구현 클래스를 가지고 있다.
만약 xml에 두 객체가 모두 DI되어 있을 경우, getBean(ExamConsole.class)했을 때 어떤 객체를 가져와야 할지몰라 에러가 발생한다. 이를 해결할 방법은 있으나 나중에 알아보겠다.
※주의사항
Spring context를 사용하기 위해서는 maven으로 라이브러리를 가져와야한다.
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
'뉴렉쳐 스프링 프레임워크 정리 > Part1. DI' 카테고리의 다른 글
[Spring 개념정리] Java를 통한 Configuration (0) | 2023.07.14 |
---|---|
[Spring 개념정리] 어노테이션을 이용한 객체생성 (0) | 2023.07.14 |
[Spring 개념정리] @Autowired 어노테이션을 이용한 DI (0) | 2023.07.14 |
[Spring 개념정리] xml을 사용한 DI 및 IoC 컨테이너 사용법2 (0) | 2023.07.14 |
[Spring 개념정리] DI와 IoC Container (0) | 2023.07.14 |