-
5. DI (Dependency Injection: 의존성 주입)Back-end Developer/Spring Framework, 설정 및 실습 2018. 12. 13. 17:26
DIDI... Spring 관련 공부나 개발, 또는 개념들을 많이 찾아보신 분들은 매우 익숙한 단어라고 생각해요.
의존성 주입 Depende... 넵
말만 보아도 어느정도 감은 오지만, 저는 말씀드렸던대로! 개념 정리와 실제로 해봐야 싹- 와닿기 때문에 하나씩 정복 해 나갈게요.
DI (Dependency Injection): 의존성 주입
프로그래밍에서 구성 요소간 의존 관계가 코드의 내부가 아닌 외부의 설정 파일 등을 통해 정의 될 수 있게하는 디자인 패턴.
- 구성 요소는 객체라고 생각하시면 됩니다.
- 객체간의 의존 관계는 어떤 객체에서 다른 객체를 생성해서 사용하는 그런 행위로 볼 수 있겠습니다.
- 외부의 설정 파일이라는 것이 바로 다른 객체를 뜻하고,
Spring에서는 유지 보수의 효율을 높이기 위해, IoC 컨테이너를 이용합니다.프로젝트 생성 및 버전 변경
new -> other -> Spring Legacy Project -> next
Simple Spring Maven 선택, 프로젝트명 지정 finish
좌측 파일 트리에 Maven Dependencies에 대한 것들이 추가되어있네요.
버전은 다른걸 사용하려구요. pom.xml에서 아래와 같이 변경하고 저장해주세요.
12345678910111213141516171819<properties><!-- Generic properties --><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- Spring --><spring-framework.version>4.2.5.RELEASE</spring-framework.version><!-- Hibernate / JPA --><hibernate.version>4.2.1.Final</hibernate.version><!-- Logging --><logback.version>1.0.13</logback.version><slf4j.version>1.7.5</slf4j.version><!-- Test --><junit.version>4.11</junit.version></properties>cs 물론 자신이 원하는 버전에 맞춰서 사용하셔도 상관 없습니다.
아 참고로 우린 웹앱이 아니기 때문에 Tomcat은 사용하지않습니다. 왜 없지? 하고 놀라지마세요. ㅎㅅㅎ
Interface 파일 생성
src/main/java 폴더 new -> package 생성 이름은 임의로 지정해주세요.
저는 kr.ac.snut.spring.di 라고 지정했습니다.
이제 요 package에 Interface 파일을 새로 생성해 주세요.
참고로 동물 관련한 객체를 생성 할 예정이므로 이름을 AnimalType으로 정했습니다.
그리고 Interface 내부에 메소드 하나를 정의해주세요. 이렇게요.
123456package kr.ac.snut.spring.di;public interface AnimalType {public void sound();}cs Interface에서 메소드는 선언만 되고, 구현안되는거 아시지요~~
Class 파일 생성
다음으로 이 Interface를 사용할 Class를 만들고 정의해 봅시다.
Dog라는 이름으로 Class 하나 생성해주세요.
그리고 Interface 추가를 해줍니다. 생성시에 미리 추가 해주세요.
Interface에서 선언했던 sound 메소드가 같이 생성되었죠? 여기서 구현하시면 됩니다.
그리고 간단하게 출력만 하기위해 코드를 구성합니다. 강아지 이름에 대한 필드도 하나 추가해주세요.
여기서 DI 처리를 해줘야합니다. 우리가 이전에 사실 DI 처리를 해봤었는데요.
Setter와 Constructor를 이용한 방법입니다.
이번엔 Setter를 이용할게요. 지난번처럼 자동적으로 Set 메소드를 불러와도 좋고
전 귀찮음의 끝이라서 Lombok Library 다시 추가해서 끝냈습니다.
123456789101112131415package kr.ac.snut.spring.di;import lombok.Setter;@Setterpublic class Dog implements AnimalType {private String dogName;@Overridepublic void sound() {System.out.println("Dog name = " + dogName + ": " + "Bow Wow");}}cs 같은 방식으로 Cat Class도 생성해주세요.
잠깐! 저 처럼 실수로 Interface 추가를 안했다면, 코드를 그대로 따라 치고,
빨간 밑줄에 마우스를 갖다대서 add unimplemented methods 누르시면 됩니다.
1234567891011121314package kr.ac.snut.spring.di;import lombok.Setter;@Setterpublic class Cat implements AnimalType{private String catName;@Overridepublic void sound() {System.out.println("Cat name = " + catName + ": " + "Meow");}}cs 다른 동물도 만드시려면 'The fox'라는 노래의 가사를 참고해서 만들어보세요. ^^
자 마지막으로 이 개와 고양이를 키우는 주인이 필요하겠죠.
PetOwner라는 이름의 Class를 하나 생성해줍니다. 얘는 사람이겠죠? Animal Type이라는 Interface는 따로 추가하지 않습니다.
그 대신 animal이라는 이름으로 AnimalType 객체를 하나 생성해주세요.
주인이 어떤 동물을 소유하는가에 대한 정보를 animal에 저장해 둘 예정인거죠.
이번엔 생성자를 통해 DI 처리 해줍시다. 까먹진 않았기를 바라며...
(마우스 오른쪽 버튼 -> source -> create contstruct using by field.. -> 해당 필드 체크 후 generate)
그리고 마지막으로 play 메소드를 하나 정의해서 거기서 특정 동물의 sound 메소드를 호출해 볼게요.
1234567891011121314package kr.ac.snut.spring.di;public class PetOwner {private AnimalType animal;public PetOwner(AnimalType animal) {this.animal = animal;}public void play() {animal.sound();}}cs 설명은 길었지만, 코드는 이렇게나 간단합니다. ㅎㅎ
Bean 등록
이제 주입된 의존성을 Bean에 등록해야하니까, Bean package를 하나 생성합니다.
우리가 처음 만든 package에 아래와 같이 생성해주세요.
XML 파일 생성
Bean 등록에 쓰일 xml 파일을 new -> other -> spring bean configuration -> next
이름을 animal.xml로 지정 후 finish 해서 생성해주세요.
wow! 이제 이 xml 파일에서 Dog, Cat, PetOwner에 대한 bean을 등록해주면
Spring 컨테이너에서 자동적으로 생성이 이루어집니다!!
이제 bean을 이 파일에 등록해 볼게요. 두가지 방법이 있어요.
- 직접 써넣기
- Editor
Bean 태그를 통해 생성한 Class를 넣어주세요.내부에 정의해 둔 필드는 Property 태그를 통해 해당 bean 태그 안에 정의합니다.12345678910<?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 = "dog" class = "kr.ac.snut.spring.di.Dog"><property name = "dogName" value = "poodle"></property></bean></beans>cs 이렇게 쓰시면되겠죠? 저장하시고, 아래의 beans 탭을 누르시면 등록된 빈을 확인하실 수 있습니다.
여기가 바로 Editor입니다. 여기서 등록하는 방법도 실시해볼게요.
New Bean... 클릭 -> Id: cat, Class: Cat 입력 후 browse 클릭 -> DI의 Cat Class 선택 후 OK
이렇게 Cat Class 등록하시면 됩니다.
Property도 추가해줘야겠죠? 생성된 빈에서 오른쪽 버튼을 눌러 Insert 선택
name: catName, value: 임의 지정 해주세요. 저는 Siam으로 넣었습니다. 훗 ^^
이렇게 Cat Bean도 다 만들었으니 PetOwner도 등록해주세요. 본인이 편하실대로 ㅎㅎ
근데 PetOwner에는 필드는 없고 Interface로 생성한 객체와 생성자만 존재했으니까 방법이 조금 다릅니다.
Editor로 만드시는 분은 Insert <constructor-arg> 선택 후 ref 란에 원하는 Class의 id를 넣어주세요.
dog나 cat 넣으시면 되겠죠? 저는 cat 넣었습니다.
'ref'는 객체에서 가져온 변수를 넣을 때 사용하는 값이에요.
위에서 Class의 일반적인 변수(여기서는 String type)는 value에 직접 값을 넣었죠. 차이점 확인하세요!
123456789101112131415161718<?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 = "dog" class = "kr.ac.snut.spring.di.Dog"><property name = "dogName" value = "poodle"></property></bean><bean id = "cat" class = "kr.ac.snut.spring.di.Cat"><property name = "catName" value = "siam"></property></bean><bean id = "petOwner" class = "kr.ac.snut.spring.di.PetOwner"><constructor-arg ref = "cat"></constructor-arg></bean></beans>cs 저처럼 구성이 되었다면 제대로 하신겁니다. 짝짝짝
이렇게 Bean을 통해 Spring 컨테이너에 등록했으니, 이제 의존성 주입이 Spring 컨테이너를 통해 이루어집니다.
객체를 계속 새로 생성하는 것이 아니라 자동적으로 컨테이너에서 만들어진다고 생각하시면 됩니다.
Main Class 파일 생성 및 실행 결과
이제 Main 함수를 만들어서 실행을 해볼게요. MainApp이란 이름으로 Class를 생성해줍니다.
12345678910111213141516package kr.ac.snut.spring.di;import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainApp {public static void main(String[] args) {ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("/kr/ac/snut/spring/di/beans/animal.xml");PetOwner person = (PetOwner) context.getBean("petOwner");person.play();context.close();}}cs 위 코드와 같이 정의해주세요. 그런데 처음보는게 하나있네요.
'ClassPathXmlApplicationContext'는 Spring 컨테이너를 생성해줍니다. 괄호 내 파일명은 Class 경로 기준입니다.
따라서 내부엔 바로 상위 package부터 경로를 잡아주시면 됩니다.
보세요! context라는 객체를 생성했어요!! 얘가 생성되면, 자동으로 bean이 생성됩니다.
bean이 생성되었으니 가져와서 써봐야겠죠?
아래에 아까 생성한 bean의 아이디(petOwner)를 통해 bean을 가져와 person 변수에 저장합니다.
bean이 person에 불려와졌으니, 해당 Class에 있던 play 메소드가 호출 가능하게됩니다. 호출해주세요! ^___^/
간단하게 여기까지 수행할 코드를 구성했으니, context를 닫아줌으로써 프로그램을 종료합니다.
또한 play 메소드 내에 sound 메소드를 호출했었으므로, 그리고 전 cat을 ref로 가져왔기 때문에,
Cat Class의 sound가 실행될겁니다.
결과
참 엉성하게도 잘 나오죠? 어쨌든 성공했네요. ㅎㅎ 고생하셨습니다. ^^
반응형'Back-end Developer > Spring Framework, 설정 및 실습' 카테고리의 다른 글
7. AOP (Aspect Oriented Programming: 관점 지향 프로그래밍) (0) 2018.12.19 6. Annotation으로 의존성 주입하기 (0) 2018.12.16 4. JSTL를 이용한 View에서 기능 처리 (참고) (0) 2018.12.11 3. JSP, Servlet을 활용한 MVC 패턴 설계 (0) 2018.12.05 2. Servlet 개념 정리 및 실습, 배포(deploy) (0) 2018.12.01