'뉴렉처' 님의 채널(www.youtube.com/user/newlec1)을 바탕으로 제작한 블로그 글입니다:)
이번 시간에는 Spring DI 지시서(Spring Bean Configuration)를 어떻게 작성하는지에 대해 방법을 알아보도록 하겠습니다.
코드는 지난시간(programming-workspace.tistory.com/13?category=913472)에 사용한 코드를 이용해 진행하겠습니다.
지난 글에서 설명드렸듯이, 아래와 같은 코드를 이용하였을 때, AnimalPrintAge의 부분을 AnimalPrintName 함수로 수정하고자 할때,
이전과 같은 방식으로는 코드를 수정해야만 해당 함수를 변경할 수 있다고 말씀드렸습니다.
public class Program {
public static void main(String[] args) {
Animal animal = new Animal("BINGO", 5);
//AnimalPrint console = new AnimalPrintName(animal);
AnimalPrint console = new AnimalPrintAge(animal);
console.print();
}
}
하지만 이러한 Dependency Injection 부분을 외부 설정에 맡김으로써 원본 코드를 수정하지 않고도 AnimalPrintAge의 부분을 AnimalPrintName 함수로 간단하게 수정할 수 있다고 했죠.
그러면 어떻게 외부 설정에서 Dependency Injection을 할 수 있는지, Bean 이란 무엇이고 어떻게 작성하는지에 대해 다뤄보겠습니다.
우선, 이전에 사용하던 코드를 수정해보겠습니다.
이전에 사용했던 방식은 생성자에 인자를 넘겨주는 방식이었습니다.
이번에는 setter을 이용하여 exam을 인자로 넘겨주는 일반적인 방식으로 결합하도록 코드를 아래와 같이 수정해보겠습니다.
- AnimalPrint.java
public interface AnimalPrint {
void print();
void setAnimal(Animal animal);
}
- AnimalPrintAge.java
public class AnimalPrintAge implements AnimalPrint {
Animal animal;
public AnimalPrintAge() {
// TODO Auto-generated constructor stub
}
public AnimalPrintAge(Animal animal) {
this.animal = animal;
}
@Override
public void print() {
System.out.printf("Age is %d", animal.getAge());
}
@Override
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
- AnimalPrintName.java
public class AnimalPrintAge implements AnimalPrint {
Animal animal;
public AnimalPrintAge() {
// TODO Auto-generated constructor stub
}
public AnimalPrintAge(Animal animal) {
this.animal = animal;
}
@Override
public void print() {
System.out.printf("Age is %d", animal.getAge());
}
@Override
public void setAnimal(Animal animal) {
this.animal = animal;
}
}
- Program.java
public class Program {
public static void main(String[] args) {
Animal animal = new Animal("BINGO", 5);
//AnimalPrint console = new AnimalPrintName(animal);
AnimalPrint console = new AnimalPrintAge();
console.setAnimal(animal);
console.print();
}
}
이제 Animal 객체나 AnimalPrintAge라는 객체가 수정된다고 가정해봅시다.
그렇다면, 코드를 수정하지 않고 수정될만한 부분을 외부 설정으로 빼는 것이 옳겠죠?
이 때, 객체가 수정된다면 객체가 관련되어있는 결합 부분까지 변경해주어야 합니다.
따라서 Program.java의 모습은 아래처럼 될 것입니다.
public class Program {
public static void main(String[] args) {
/*
Animal animal = new Animal("BINGO", 5);
AnimalPrint console = new AnimalPrintAge();
console.setAnimal(animal);
*/
AnimalPrint console = //Spring이 넘겨줄 부분//;
console.print();
}
}
즉, 위의 주석 부분을 Spring이 알아서 조립을 해서 주면, 아래의 console이 조립된 것을 받으면 되는 것이죠.
그렇다면 Spring이 조립해주는 주석의 부분을 spring에게 넘겨줄 지시서로 작성하면 되겠네요.
지시서를 작성하기 위해 지난 시간에 만들어두었던 setting.xml을 열어줍니다.
우리에게 현재 필요한 부분은 아래와 같음을 다시 상기시켜봅시다.
Animal animal = new Animal("BINGO", 5);
AnimalPrint console = new AnimalPrintAge();
console.setAnimal(animal);
흐름을 보니, 먼저 두개의 객체를 생성한 후에 그 객체들을 결합하는 순서대로 작성하면 된다는 걸 확인할 수 있습니다.
1. 인자 없는 생성자로 객체 생성하기
우선 AnimalPrint console = new AnimalPrintAge(); 부터 만들어봅시다.
우리는 bean이라는 것을 이용하여 어떤 객체를 만들어달라고 아래와 같이 지시할 수 있습니다.
console 인스턴스를 AnimalPrintAge 객체로 만들어주세요
= AnimalPrint console = new AnimalPrintAge()
=>
<bean id = "console" class = "spring.console.AnimalPrintAge" />
이 때 주의할 점은, 하나의 프로젝트 안에 AnimalPrintAge라는 이름이 여러개 있을 것을 방지하여 패키지 명까지 함께 써주어야 한다는 점입니다.
2. 인자 있는 생성자로 객체 생성하기
그렇다면, Animal animal = new Animal("BINGO", 5); 와 같이 생성자에 인자가 있는 경우는 어떻게 해야할까요?
바로 다음과 같이 코드를 작성해 주면 됩니다.
Animal animal = new Animal("BINGO", 5);
=>
<bean id = "animal" class = "spring.entity.Animal">
<constructor-arg type="java.lang.String" value="BINGO"/>
<constructor-arg type="int" value="5"/>
</bean>
그러면 animal과 console 객체 생성은 모두 완료했습니다.
이제 console의 setAnimal을 이용하여 출력해야합니다.
3. 객체의 메소드 호출하기
이번에는 console.setAnimal(animal); 의 부분을 작성해봅시다.
함수를 이용하기 위해서는 함수를 부르는 객체 부분,
즉 위의 <bean id = "console" class = "spring.console.AnimalPrintAge" /> 을 이용하여 작성해야합니다.
이 때, 함수를 사용하기 위해서 property라는 것을 사용하는데 property 안에는 아래와 같은 속성이 있습니다.
<property name = "" value = "" ref = "">
name은 함수의 이름이 들어가고, value와 ref에는 인자의 이름이 들어가는데요,
이 때 주의할 점은 인자의 type이 value 타입이냐, reference 타입이냐에 따라서 들어가는 위치가 다르다는 점입니다.
해당 부분을 아래와 같이 수정할 수 있습니다.
console의 setAnimal 함수에 animal(지시서에서 생성한 인스턴스의 이름과 동일해야 함)을 인자로 넘겨주세요.
animal은 레퍼런스 형식이니 ref에 넣어줍니다.
= console.setAnimal(animal);
=>
<bean id = "console" class = "spring.console.AnimalPrintAge">
<property name = "animal" ref = "animal" />
</bean>
만약 값이 value 형식이라면 아래의 두 가지 방식 중에 하나를 선택해서 사용하면 됩니다.
방법 1.
<bean id = "console" class = "spring.console.AnimalPrintAge">
<property name = "animal" value = "10" />
</bean>
방법 2.
<bean id = "console" class = "spring.console.AnimalPrintAge">
<property name = "animal">
<value> 10 </value>
</property>
</bean>
이 때, 자세히 보면 무언가 이상한 부분이 있습니다.
함수의 이름은 setAnimal인데, 왜 property의 name은 animal인걸까요?
이는 setAnimal이라는 함수의 이름때문입니다.
지시서를 작성할 때에, property의 name에 들어갈 함수가 set~~ 으로 되어있다면,
setAnimal의 set부분을 지우고, 남은 Animal의 앞글자를 소문자로 바꿔서 적어줍니다.
또한, animal은 reference type이기 때문에 ref 안에 인스턴스명을 적어주어야합니다.
이로써 지시서를 통해 Injection을 하는 방식을 배워보았습니다.
다음시간에는 지시서에서 작성한 내용을 넘겨줄 주체를 생성하여 실행해보도록 하겠습니다.
'Spring > Dependency Injection' 카테고리의 다른 글
[Spring Framework] 이클립스에서 Spring Library 가져오기 (0) | 2021.01.06 |
---|---|
[Spring Framework] Application Context 사용하기 (0) | 2021.01.05 |
[Spring Framework] 이클립스에서 Spring 사용하기 (0) | 2020.12.26 |
[Spring Framework] 직접 Dependency Injection 해보기 (0) | 2020.12.26 |
[Spring Framework] IoC 컨테이너 (0) | 2020.12.26 |