Kim Hyeong
Spring Framework의 기본적인 개념 본문
Spring Framework의 기본적인 개념
Library vs Framework
- 라이브러리란 자주사용하는 코드를 함수나 클래스로 묶어 놓고 가져다 쓰는것, 프로그램의 전체 설계에는 영향을 주지 않는다.
- 즉 라이브러리라는 단순히 기능만 제공하는것 , 개발자의 능력에따라 같은 라이브러리를 사용해도 전체 설계는 차이가 있음
- 프레임워크는 프로그램을 어떻게 짜야한다는 규칙이 있다. 내가 만들어야하는 파일, 폴더들이 다 제공이 되어있음
- 즉 프레임워크는 이미 프로그램이 돌아가는 기반 틀이 만들어 져있고 개발자는 그 안에 코드를 집어 넣어서 프로그램을 만든다. -> 따라서 라이브러리와 달리 누가 하든지 간에 비슷한 코드품질을 가질 수 있다.
- 따라서 회사 입장에서는 유지보수성과 재활용성이 높은 프레임워크 기반으로 프로그램을 만든다.
- 좀더 쉽게 정리하면 라이브러리는 내 코드로 불러와 사용하는것이고, 프레임워크는 내 코드를 집어 넣어서 사용한다고 보면 된다.
Spring Framework
Composition
- 하나의 객체가 다른 객체를 사용하는 방식
- 하나의 객체가 다른 객체를 사용해야 하는데 이때 직접 객체를 생성해서 사용하는 방식. -> ex)Service가 메서드 내에서 DAO를 직접 만들어서 사용하는 방식
- BookService와 BookDAO, 2개의 클래스 관계가 아주 밀접한 관계
- 클래스간에 관계가 tightly coupled : 딱 결합이 되어 사용해야하는 관계, 즉 재사용성의 관점에서는 좋지 않다.
- 하나의 클래스내에서 다른 클래스명이 명시적으로 등장하기 때문에 그렇다.
- 아래 코드는 일반적인 Composition 방식의 예이다. Service 클래스의 메서드 내에 DAO 객체를 직접 생성함.
//Controller
public class BookController {
Scanner s;
public BookController()
{
s = new Scanner(System.in);
System.out.print("키워드입력 =>");
String keyword = s.nextLine();
BookService service = new BookService();
ArrayList<BookDTO> list = service.findBookByKeyword(keyword);
for(BookDTO dto : list)
{
System.out.println(dto.getBtitle() +", " + dto.getBauthor());
}
}
}
//Service
public class BookService {
private BookDAO dao;
public BookService(BookDAO dao) {
this.dao = dao;
}
public BookDAO getDao() {
return dao;
}
public void setDao(BookDAO dao) {
this.dao = dao;
}
public ArrayList<BookDTO> findBookByKeyword(String keyword) {
//composition 방식
BookDAO dao = new BookDAO();
return dao.select(keyword);
}
}
Aggregation
- 하나의 객체와 다른 객체를 결합해서 사용하는 방식
- 그럼 어떻게 결합을 하는가? -> Service 내에 dao 필드를 만들고 , 조립자인 Controller를 이용한다.
- 방법1: 조립자인 Controller 클래스가 Service 클래스의 getter/setter를 이용해 dao를 넘겨 객체들을 결합한다.
- 방법2: 조립자인 Controller 클래스가 Service 클래스의 생성자를 이용하여 dao를 넘겨 객체들을 결합한다.
- 아래코드는 Aggregation 방식의 예이다. getter/setter를 이용한 방식 그리고 생성자를 이용한 방식 2가지를 보여주고 있으며 Controller가 조립자 역할을 수행하고 있다.
//Controller
public class BookController {
Scanner s;
public BookController()
{
s = new Scanner(System.in);
System.out.print("키워드입력 =>");
String keyword = s.nextLine();
//Aggregation
//Service와 DAO를 결합하기위해 Controller에 DAO와 Service 객체를 만들고
//setter 를 이용해 DAO를 service에 넘김. or 생성자 이용
/*Aggregation 방법1
BookDAO dao = new BookDAO();
BookService service = new BookService();
service.setDao(dao);
*/
//Aggregation 방법2
BookDAO dao = new BookDAO();
BookService service = new BookService(dao);
ArrayList<BookDTO> list = service.findBookByKeyword(keyword);
for(BookDTO dto : list)
{
System.out.println(dto.getBtitle() +", " + dto.getBauthor());
}
}
}
//Service
public class BookService {
private BookDAO dao;
public BookService(BookDAO dao) {
this.dao = dao;
}
public BookDAO getDao() {
return dao;
}
public void setDao(BookDAO dao) {
this.dao = dao;
}
public ArrayList<BookDTO> findBookByKeyword(String keyword) {
/*
//composition 방식
//BookDAO dao = new BookDAO();
*/
//transaction 은 데이터베이스가 수정이 되었을때 사용하는것
//select 시에는 필요 없다.
return dao.select(keyword);
}
}
Interface 기반의 Aggregation 방식
- 비록 Composition 방식에서 Aggregation 방식으로 바꾸어 객체를 직접적으로 생성하지는 않지만, 아직도 Service 필드에 다른 클래스이름이 적혀있음 즉 DAO가 명시되어있다.
- 이를 인터페이스를 이용하여 클래스간의 겹합도를 낮추는 작업을 수행한다.
- 예를들어 DAO interface를 하나 만들고 이를 implements 하여 MySQL용 DAO 1개와, Oracle용 DAO 1개를 만들었다고 하자.
- IS-A 관계가 성립되므로 Service 쪽에서는 필드에 인터페이스 DAO로 인스턴스를 하나 지정해놓고(ex: private DAO dao;) Controller 단에서 Orale용 DAO 또는 MySQL용 Dao를 service 생성자인자로 넘겨주면 된다.
- 그러면 코드를 많이 바꿀필요없이 느슨한 결합으로 코드 구성이 가능하다 .
//Controller
package exam_01_01_composition.controller;
import java.util.ArrayList;
import java.util.Scanner;
import exam_01_01_composition.DAO.BookDAO;
import exam_01_01_composition.DAO.BookDAOOracle;
import exam_01_01_composition.DTO.BookDTO;
import exam_01_01_composition.service.BookService;
public class BookController {
Scanner s;
public BookController()
{
s = new Scanner(System.in);
System.out.print("키워드입력 =>");
String keyword = s.nextLine();
//Aggregation
//Service와 DAO를 결합하기위해 Controller에 DAO와 Service 객체를 만들고
//setter 를 이용해 DAO를 service에 넘김. or 생성자 이용
//생성자 이용 방식
//★★★★ interface를 이용해 dao를 구성하였으므로
//아래처럼 Controller 단에서 DB에 맞는 인스턴스만 생성해 Service에 넘기면됨
//물론 Service 단에 필드로 DAO 인스턴스를 만들어 놔야함.
//BookDAO dao = new BookDAO();
BookDAOOracle dao = new BookDAOOracle();
BookService service = new BookService(dao);
ArrayList<BookDTO> list = service.findBookByKeyword(keyword);
for(BookDTO dto : list)
{
System.out.println(dto.getBtitle() +", " + dto.getBauthor());
}
}
}
//Service
package exam_01_01_composition.service;
import java.util.ArrayList;
import exam_01_01_composition.DAO.BookDAO;
import exam_01_01_composition.DAO.DAO;
import exam_01_01_composition.DTO.BookDTO;
public class BookService {
//★★ 필드에 interface DAO로 인스턴스 생성
private DAO dao;
public BookService(DAO dao) {
this.dao = dao;
}
public DAO getDao() {
return dao;
}
public void setDao(BookDAO dao) {
this.dao = dao;
}
public ArrayList<BookDTO> findBookByKeyword(String keyword) {
return dao.select(keyword);
}
}
//Interface DAO
package exam_01_01_composition.DAO;
import java.util.ArrayList;
import exam_01_01_composition.DTO.BookDTO;
public interface DAO {
ArrayList<BookDTO> select(String keyword);
}
//MYSQL DAO
package exam_01_01_composition.DAO;
import exam_01_01_composition.DTO.BookDTO;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
public class BookDAO implements DAO {
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;
}
}
//Oracle DAO
package exam_01_01_composition.DAO;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import exam_01_01_composition.DTO.BookDTO;
public class BookDAOOracle implements DAO {
public ArrayList<BookDTO> select(String keyword) {
//제네릭을 이용해 BookDTO형 ArrayList만듬
ArrayList<BookDTO> list = new ArrayList<BookDTO>();
try{
//1. 드라이버 로딩
//자바프로그램이 MySQL에 접근하기 위해서 필요한 라이브러리를 불러들인다.
//pom.xml 에 MySQL에 대한 dependency를 입력해서 라이브러리를 다운로드 받는다.
Class.forName("com.oracle.jdbc.Driver");
//2. 실제 데이터베이스에 접속
//어떤 데이터베이스에 접속할 건지, 아이디와 패스워드가 필요
String url = "jdbc:orcle://localhost:1582/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;
}
}
IoC(Inversion of Control - 제어의 역전)
- 기존 Composition(일반적인 프로그램 흐름)방식과 비교되는 방식
- 기존 제어 흐름을 거꾸로 뒤집는 개념
- 객체는 자신이 사용할 객체를 스스로 선택하지도 생성하지도 않는다. -> Interface 기반의 Aggregation 방식
- 객체는 자신도 어떻게 만들어지고 어디에서 사용되는지 알 수 없다.
- 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문
- 모든 겍체는 제어 권한을 갖는 특별한 객체에 의해서 생성되고 사용이 결정된다.
- 일반적으로 Framework 라고하면 IoC의 개념이 적용되어있다. -> 즉 객체를 조합할 수 있는 기능을 가지고 있어야한다.
- 객체를 결합하는 과정을 Spring이 해준다.
DI(Dependency Injection - 의존성 주입)
- 종속객체(DAO) : Service에서 사용되는 객체
- 종속객체(Dependency)를 사용할려는 객체에 주입(Injection)하려는 행동
- Spring은 Dependency Injection을 처리해주는 Container 역할을 한다.
'Spring' 카테고리의 다른 글
스프링 DI(Dependency Injection) 1 (0) | 2018.08.20 |
---|---|
스프링 MVC 흐름과 주요 구성 컴포넌트 (0) | 2018.08.16 |
DI의 Life Cycle (0) | 2018.08.10 |
지금까지 배운 DI 와 IoC 정리 (0) | 2018.08.10 |
Spring Framework 실습 - Java Class를 이용한 방식 (0) | 2018.08.10 |
Comments