스프링 프레임워크(6) 의존성 주입

넙데데맨·2022년 4월 20일

의존성 주입

애플리케이션은 각각 기능 담당하는 컴포넌트로 이뤄짐
컴포넌트는 세부기능 수행하는 클래스로 이뤄짐
다른 클래스의 생성자를 호출해 사용할 경우 기능 구현 과정에서 빠르게 대처하기 힘들다.
스프링 프레임워크에서는 각 클래스 연관 관계를 스프링 설정을 통해 맺어줘 클래스들이 연관 관계를 갖지 않게 구현한다.

의존성 주입 사용전

boardController.java

	public class BoardController extends HttpServlet{
    	BoardService boardService;
        
        public void init() throws ServletException{
        	boardService = new BoardService();
        }
	}

boardService 클래스의 기능을 사용하기 위해 생성자 호출해 boardService 객체를 코드에서 직접 생성해 사용
BoardService.java

	public class BoardService{
    	boardDAO boardDAO;
    	public BoardService(){
        	boardDAO = new BoardDAO;
        }
    }

boardService 역시 마찬가지로 boardDAO 클래스 사용 위해 객체 직접 생성
boardDAO의 클래스 기능 변경 시 연관된 클래스들을 전부 변경해줘야할 수도 있다.

인터페이스 적용 게시판 기능

boardServiceImpl.java

	public class BoardServiceImpl implments BoardService{
    	BoardDAO boardDAO;
    	public BoardService(){
        	boardDAO = new BoardOracleDAOImpl; // BoardDAO 구현 클래스
        }
    }

중간에 MySQL로 DB가 바뀔 시

//boardDAO = new BoardOracleDAOImpl;
boardDAO = new BoardMySQLDAOImpl;

해당 부분만 교체해주면 된다. 하지만 소스코드에서 직접 수정해야하는 불편함이 잇다.

의존성 주입 적용 게시판 기능

boardServiceImpl.java

	public class BoardServiceImpl implments BoardService{
    	private BoardDAO boardDAO;
    	public BoardServiceImpl(BoardDAO boardDAO){
        	this.boardDAO = boardDAO;
        }
    }

boardServiceImpl 클래스는 생성자를 호출할 때 컨테이너에 의해 주입되는 객체로 boardDAO 변수를 초기화한다.
이처럼 의존하는 객체를 컨테이너 실행 시 주입하기 때문에 DI라고 부른다. 의존성 주입 방식에는 생성자를 통한 방식과 setter를 통한 주입 방식이 있다.

1. 값 형식 DI

<bean id="exam" class="spring.di.entity.NewlecExam">
  <property name="kor" value="10"/>
  <property name="eng" value="20"/>
  <property name="math" value="30"/>
  <property name="com" value="40"/>
</bean>

<bean id="console" class="spring.di.ui.InlineExamConsole">
  <property name="exam" ref="exam"/>
</bean>

2. 생성자 DI

KimExam.java

	public KimExam(int kor, int eng, int math, int com) {
		this.kor = kor;
		this.eng = eng;
		this.math = math;
		this.com = com;
	}

setting.xml

	<bean id="exam" class="spring.di.entity.NewlecExam">
	  <constructor-arg value="10" />
	  <constructor-arg value="20" />
	  <constructor-arg value="30" />
	  <constructor-arg value="40" />
	</bean>

문제 어떤 필드를 초기화하는 지 알기 쉽지 않다!

	<bean id="exam" class="spring.di.entity.NewlecExam">
	  <constructor-arg index="0" value="10" />
	  <constructor-arg index="1" value="20" />
	  <constructor-arg index="3" value="30" />
	  <constructor-arg index="2" value="40" />
	</bean>
	<bean id="exam" class="spring.di.entity.NewlecExam">
	  <constructor-arg name="kor" value="10" />
	  <constructor-arg name="eng" value="20" />
	</bean>

문제 어떤 타입인지 알 수 없다.

	<bean id="exam" class="spring.di.entity.NewlecExam">
	  <constructor-arg name="kor" type="float" value="10" />
	  <constructor-arg name="eng" type="int: value="20" />
	</bean>

설정 파일 처리기 추가


1. xml 파일의 Namespaces 탭 p에 체크

2.beans 태그에xmlns:p="http://www.springframework.org/schema/p" 처리기가 추가됨
3.

<bean id="exam" class="spring.di.entity.NewlecExam" p:kor="10"/>

namespace p 추가

namespace
같은 이름을 가진 것들을 구분하기 위한 것
위 코드의 p:kor 는 p가 처리할 kor 이라는 뜻
태그나 일반 속성에 사용이 가능하다.
bean의 하위 태그인 property 태그 대신 네임스페이스 p를 이용해 bean태그의 속성에서 바로 값을 입력할 수 있다.

3. 컬렉션 생성과 목록 DI

Java 코드

List<Exam> exams = new ArrayList<>();
exams.add(new NewlecExam(1,1,1,1));
for(Exam e : exams) System.out.println(e);

List에 추가하기 위해 쓰이는 add 메서드 기능을
xml 파일에서 property에서 사용할 수가 없다.

ArrayList는 생성자에 Collection을 대입할 수 있다.

<bean id="exams" class="java.util.ArrayList">
	<constructor-arg>
		<list>
			<bean class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10"/>
			<ref bean="exam"/>
		</list>
	</constructor-arg>
</bean>	

namespace util 추가

<util:list id="exams" list-class="java.util.ArrayList">
	<bean class="spring.di.entity.NewlecExam" p:kor="20" p:eng=""/>
	<ref bean="exam"/>
</util:list>

차이점 : namespace util을 사용 시 실제로 객체를 만들 수가 있다.

리스트 추가 방법
<bean class="spring.di.entity.NewlecExam" p:kor="10" p:eng="10"/>
리스트 안에 집어넣는 것이기 때문에 id 속성은 필요 없다.
<ref bean="exam"/>
이미 만들어진 객체를 참조하여 넣을 수도 있다.

알아본 것

xml 파일을 통해 객체를 초기화 사용하는 법

  • 값 DI
  • 생성자 DI

namespace를 통한 초기화 및 리스트 초기화

  • p : 타입을 알아서 넣어주는 네임스페이스
  • util

property를 사용할 땐 해당 객체의 setter 함수를 사용
constructor-arg를 사용할 땐 해당 객체의 생성자를 사용해 값을 주입해준다

profile
차근차근

2개의 댓글

comment-user-thumbnail
2022년 4월 21일

잘보고갑니다

1개의 답글