Hyokyun Yim bio photo

Hyokyun Yim

Koreatech Computer Science Engineering undergraduate 4 grade.

Facebook Github

Spring Framework 를 직접 사용해 보면서 IoC , DI 개념을 익혀보자

Overview

Spring Framework 실습 - XML을 이용한 방식

  • Spring은 DI(한 객체를 다른 객체에 주입하는 방식)를 처리해주는 Container 역할을 수행한다.
  • Spring을 Controller라고 보면 안된다!! Controller와는 전혀 다른 역할을 수행함
  • DI에대한 세부명세, 즉 어떤 객체를 어떻게 사용할것인지 XML 파일에 저장이 되어있다.
  • Spring은 이 XML파일을 읽어서 객체를 생성하고 동작을 수행한다.
  • 즉 Main 에서 Spring 컨테이너를 생성할때 XML 파일에 기입되어있는정보(어떤 클래스에서 어떤 인스턴스를 생성할 것인가)를 바탕으로 객체를 생성한다.
  • Setter Injection 방식과 Constructor Injection 방식 2가지로 DI를 구현할 수 있다.

Setter Injection 방식

  • bean 묶음은 하나의 인스턴스를 의미, 즉 지정된 클래스로부터 인스턴스를 만들어 지정한 id로 만들어라는 의미
  • Property는 지정된 bean의 setter를 이용하겠다는 의미이다. name으로 넣어준 명칭에 맞는 필드의 setter를 사용함
  • ref 는 Setter에 넘기는 인자이다. bean=”dao” 이면 Setter로 넘기는 인자는 dao가 된다.
<!-- applicationCtx.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">


  <!-- 스프링이 xml을 보고 아래 2개의 객체를 만듬 -->
  <!-- 어떤 Bean을 만들고 어떤 연관이 있는지 기입이 되있다. -->
  
  <!-- BookDAO 로부터  인스턴스를 만들어 dao로 지정한다는 의미. -->
	<bean id="dao" 
		class ="exam_02_01_BookSearch_XML_Setter.dao.BookDAO" />


  <!-- BookService 로부터  인스턴스를 만들어 service로 지정한다는 의미. -->
	<bean id="service"
		class="exam_02_01_BookSearch_XML_Setter.service.BookService">
			
			<!-- property는 setter를 이용하겠다는 의미 service 클래스의 dao를 가리키는거고 this.dao -->
			<property name="dao">				
				
				<!-- ref는  Setter에 넘기는 인자이다. 즉 Setter로 넘기는 인자 dao -->
				<ref bean="dao"></ref>
				
				<!-- 결국 setter 함수를 구현하기 위한 구문임.	
					public void setDao(BookDAO dao) 
					{
					this.dao = dao;
					}
					
				  -->
			</property>
	</bean>


</beans>

//Main


package exam_02_01_BookSearch_XML_Setter;

import java.util.ArrayList;
import java.util.Scanner;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;
import exam_02_01_BookSearch_XML_Setter.service.BookService;

public class Main {

	public static void main(String[] args) {
		
		//DI 즉 주입을 어떻게 할건지 xml문서에 기입이 되어있음
		//스프링 컨테이너인 ctx가 config를 보고 DI를 수행함
		
		//applicationCtx.xml 는 리소스 폴더에 있어야함.
		String config ="classpath:applicationCtx.xml";
		//DI 작업을해주는 스프링 객체
		//XML파일을 이용해서 Spring Container를 생성한다.
		//그러면 XML 있는 설정대로 Bean이라고 불리는 객체를 만든다.
		AbstractApplicationContext ctx = new GenericXmlApplicationContext(config);
		
		Scanner s = new Scanner(System.in);
		System.out.print("키워드를 입력하세요=>");

		String keyword = s.nextLine();
		
		//new를 써서 service 객체를 직접만드는게 아니라 스프링컨테이너에서 꺼내 사용함.
		//스프링 컨테이너에서 필요한 service 객체를 하나 끄집어 냄 , Service의 클래스 타입을 직접 명시도 해줘야함.
		BookService service = ctx.getBean("service" , BookService.class);
		ArrayList<BookDTO> list = service.findBookByKeyword(keyword);
		
		for(BookDTO dto : list)
		{
			System.out.println(dto.getBtitle() + ", " + dto.getBauthor());
		
		}
	}

}
//Service

package exam_02_01_BookSearch_XML_Setter.service;

import java.util.ArrayList;

import exam_02_01_BookSearch_XML_Setter.dao.BookDAO;
import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;

public class BookService {

	private BookDAO dao;
	
	public BookDAO getDao() {
		return dao;
	}

	public void setDao(BookDAO dao) {
		this.dao = dao;
	}

	public ArrayList<BookDTO> findBookByKeyword(String keyword) {
		//DAO가 필요해요
		return dao.select(keyword);
	}

}



//DAO

package exam_02_01_BookSearch_XML_Setter.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;

import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;

public class BookDAO {

	public ArrayList<BookDTO> select(String keyword) {
	
		//제네릭을 이용해 BookDTO형 ArrayList만듬
		ArrayList<BookDTO> list = new ArrayList<BookDTO>();

		try{
			//1. 드라이버 로딩
			//자바프로그램이 MySQL에 접근하기 위해서 필요한 라이브러리를 불러들인다.
			//pom.xml 에 MySQL에 대한 dependency를 입력해서 라이브러리를 다운로드 받는다.
			Class.forName("com.mysql.jdbc.Driver");
			
			//2. 실제 데이터베이스에 접속
			//어떤 데이터베이스에 접속할 건지, 아이디와 패스워드가 필요
			String url = "jdbc:mysql://localhost:3306/library";
			String id = "root";
			String pw = "cps431";
			Connection con = DriverManager.getConnection(url,id,pw);	
			
			//3. SQL문을 실행하기 위한 Statement를 생성한다.
			String sql ="select btitle,bauthor from book where btitle like ?";
			PreparedStatement pstmt = con.prepareStatement(sql);
			
			//sql문에 내가 원하는 문자열을 넣는 작업
			//첫번째 물음표에 , keyword를 넣는다.
			//% 와일드문자는 0개이상의 문자를 의미한다. 즉 keyword를 포함하고 있는 문자열을 ?에 넣는다.
			pstmt.setString(1,"%"+ keyword + "%"); 
			
			
			//4. Statement 실행!!
			//수행한 쿼리문의 결과를 가져옴
			//rs 는 테이블 라인을 가리키는 포인터. 한칸씩 내려가면서 라인을 가리킴
			ResultSet rs = pstmt.executeQuery();
			
			//5. 결과처리
			//여기서 얻은 데이터를 어떻게 해서든 Controller 까지 전달하여 출력
			//DTO가 책 1권에 대한 데이터를 담을 수 있으니까.. DTO를 여러개 만들어서 결과로 나온 여러권의 책을 담아서 
			//Controller에게 전달한다!!
			while(rs.next())
			{
				//한 책에대한 정보가 담긴 rs를 dto에 때려박음
				BookDTO dto = new BookDTO();
				dto.setBtitle(rs.getString("btitle"));
				//dto.setBisbn(rs.getString("bisbn"));
				//dto.setBprice( rs.getInt("bprice")  );
				dto.setBauthor(rs.getString("bauthor"));
				
				//한권의 책정보 dto를 리스트에 넣음
				list.add(dto);
				
			}
		
			//6. 사용한 리소스 정리
			rs.close();
			pstmt.close();
			con.close();
			
			
		}catch(Exception e){
			//만약 오류가 생기면 오류 출력
			System.out.println(e);
		}
		
		return list;
	}

}


//DTO

package exam_02_01_BookSearch_XML_Setter.dto;

public class BookDTO {

	private String btitle;
	private String bauthor;
	
	
	public String getBtitle() {
		return btitle;
	}
	public void setBtitle(String btitle) {
		this.btitle = btitle;
	}
	public String getBauthor() {
		return bauthor;
	}
	public void setBauthor(String bauthor) {
		this.bauthor = bauthor;
	}
	
	
	
}

Constructor Injection

  • Setter injection 코드에서 xml과 BookService class의 코드를 Constructor를 사용하는 방식으로 수정해준다.
  • constructor-arg 는 생성자를 사용하겠다는 의미.
  • ref 로 지정된 명칭을 Constructor의 인자로 넘긴다.

<?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">


  <!-- 스프링이 xml을 보고 아래 2개의 객체를 만듬 -->
  <!-- 어떤 Bean을 만들고 어떤 연관이 있는지 기입이 되있다. -->
  
 <!-- BookDAO 로부터  인스턴스를 만들어 dao로 지정한다는 의미. -->
	<bean id="dao" 
		class ="exam_02_01_BookSearch_XML_Setter.dao.BookDAO" />


 <!-- BookService 로부터  인스턴스를 만들어 service로 지정한다는 의미. -->
	<bean id="service"
		class="exam_02_01_BookSearch_XML_Setter.service.BookService">
			
			<!-- constructor injection 방식 사용 -->
			<constructor-arg>
				<!-- ref는  constructor 넘기는 인자이다. -->
				<ref bean="dao"></ref>
			</constructor-arg>

	</bean>
	
</beans>


//Service

package exam_02_01_BookSearch_XML_Setter.service;

import java.util.ArrayList;

import exam_02_01_BookSearch_XML_Setter.dao.BookDAO;
import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;

public class BookService {

	private BookDAO dao;
	
	
	//생성자가 받아와서 필드에 설정하는 방법 - Constructor injection
	public BookService(BookDAO dao)
	{
		this.dao = dao;
	}

	public ArrayList<BookDTO> findBookByKeyword(String keyword) {
		//DAO가 필요해요
		return dao.select(keyword);
	}

}

Keyword를 xml파일에 포함시켜 Setter Injection을 통해서 주입하기

  • Main 코드에서 직접 사용자로부터 받던 책 검색 keyword 를 제거
//Main


package exam_02_01_BookSearch_XML_Setter;

import java.util.ArrayList;
import java.util.Scanner;

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.GenericXmlApplicationContext;

import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;
import exam_02_01_BookSearch_XML_Setter.service.BookService;

public class Main {

	public static void main(String[] args) {
		
		//DI 즉 주입이 어떻게 할건지 xml문서에 기입이 되어있음
		//스프링 컨테이너인 ctx가 config를 보고 DI를 수행함
		
		//applicationCtx.xml 는 리소스 폴더에 있어야함.
		String config ="classpath:applicationCtx.xml";
		//DI 작업을해주는 스프링 객체
		//XML파일을 이용해서 Spring Container를 생성한다.
		//그러면 XML 있는 설정대로 Bean이라고 불리는 객체를 만든다.
		AbstractApplicationContext ctx = new GenericXmlApplicationContext(config);
		
		
		//new를 써서 service 객체를 직접만드는게 아니라 스프링컨테이너에서 꺼내 사용함.
		//스프링 컨테이너에서 필요한 service 객체를 하나 끄집어 냄 , Service의 클래스 타입을 직접 명시도 해줘야함.
		BookService service = ctx.getBean("service" , BookService.class);
		ArrayList<BookDTO> list = service.findBookByKeyword();
		
		for(BookDTO dto : list)
		{
			System.out.println(dto.getBtitle() + ", " + dto.getBauthor());
		
		}
	}

}


  • keyword를 setter 방식을 사용하여 주입을 한다.
  • property로 setter를 사용하겠다고 지정하고, value로 원하는 검색값을 지정

<?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">


  <!-- 스프링이 xml을 보고 아래 2개의 객체를 만듬 -->
  <!-- 어떤 Bean을 만들고 어떤 연관이 있는지 기입이 되있다. -->
  
 <!-- BookDAO 로부터  인스턴스를 만들어 dao로 지정한다는 의미. -->
	<bean id="dao" 
		class ="exam_02_01_BookSearch_XML_Setter.dao.BookDAO" />

	
	
 <!-- BookService 로부터  인스턴스를 만들어 service로 지정한다는 의미. -->
	<bean id="service"
		class="exam_02_01_BookSearch_XML_Setter.service.BookService">
			
			<!-- constructor injection 방식 사용 -->
			<constructor-arg>
				<!-- ref는  constructor에 넘기는 인자이다.  -->
				<ref bean="dao"></ref>
			</constructor-arg>
			
			<!-- 책제목 keyword를 사용자로부터 직접 받는게 아니라 xml 파일에 포함시켜 Setter injection을 통해서 주입 -->
			<property name="keyword">
			<value>자바</value>
			</property>

	</bean>
	
</beans>

  • BookService에 keyword 필드를 추가해준다.

//Service 

package exam_02_01_BookSearch_XML_Setter.service;

import java.util.ArrayList;

import exam_02_01_BookSearch_XML_Setter.dao.BookDAO;
import exam_02_01_BookSearch_XML_Setter.dto.BookDTO;

public class BookService {

	private BookDAO dao;
	private String keyword;
	
	public String getKeyword() {
		return keyword;
	}

	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	//생성자가 받아와서 필드에 설정하는 방법 - Constructor injection
	public BookService(BookDAO dao)
	{
		this.dao = dao;
	}

	public ArrayList<BookDTO> findBookByKeyword() {
		//DAO가 필요해요
		return dao.select(keyword);
	}

}