📢학생정보를 처리하는 DAO 클래스가 반드시 상속받아야 되는 인터페이스
→ 객체간의 결합도를 낮추어 유지보수의 효율성 증가📃StudentDAO.java(인터페이스)
※ xyz.itwill05.di 패키지에 StudentDAO.java 인터페이스 생성
package xyz.itwill05.di; // import java.util.List; // //학생정보를 처리하는 DAO 클래스가 반드시 상속받아야 되는 인터페이스 //→ 객체간의 결합도를 낮추어 유지보수의 효율성 증가 public interface StudentDAO { int insertStudent(Student student); int updateStudent(Student student); int deleteStudent(int num); Student selectStudent(int num); List<Student> selectStudentList(); }
📢DAO 클래스 : 저장매체(File, DBMS 등)에 대한 행 삽입,변경,삭제,검색 기능을 제공하는 클래스
→ 저장매체의 종류 또는 방법에 따라 DAO 클래스 변경 가능
→ DAO 클래스가 변경돼도 DAO 클래스와 관계가 있는 클래스(Service 클래스)에 영향을 최소화하기 위해 인터페이스를 상속받아 작성 - 결합도를 낮춰 유지보수 효율성 증가📃StudentJdbcDAO.java(클래스)
※ xyz.itwill05.di 패키지에 StudentJdbcDAO.java 클래스 생성
package xyz.itwill05.di; // import java.util.List; // //DAO 클래스 : 저장매체(File, DBMS 등)에 대한 행 삽입,변경,삭제,검색 기능을 제공하는 클래스 //→ 저장매체의 종류 또는 방법에 따라 DAO 클래스 변경 가능 //→ DAO 클래스가 변경돼도 DAO 클래스와 관계가 있는 클래스(Service 클래스)에 영향을 최소화하기 위해 인터페이스를 상속받아 작성 - 결합도를 낮춰 유지보수 효율성 증가 public class StudentJdbcDAO implements StudentDAO { public StudentJdbcDAO() { System.out.println("### StudentJdbcDAO 클래스의 기본 생성자 호출 ###"); } @Override public int insertStudent(Student student) { System.out.println("*** StudentJdbcDAO 클래스 insertStudent(Student student) 메소드 호출 ***"); return 0; } @Override public int updateStudent(Student student) { System.out.println("*** StudentJdbcDAO 클래스 updateStudent(Student student) 메소드 호출 ***"); return 0; } @Override public int deleteStudent(int num) { System.out.println("*** StudentJdbcDAO 클래스 deleteStudent(int num) 메소드 호출 ***"); return 0; } @Override public Student selectStudent(int num) { System.out.println("*** StudentJdbcDAO 클래스 selectStudent(int num) 메소드 호출 ***"); return null; } @Override public List<Student> selectStudentList() { System.out.println("*** StudentJdbcDAO 클래스 selectStudentList() 메소드 호출 ***"); return null; } }
📢학생정보를 처리하는 Service 클래스가 반드시 상속받아야 되는 인터페이스
📃StudentService.java(인터페이스)
※ xyz.itwill05.di 패키지에 StudentService.java 인터페이스 생성
package xyz.itwill05.di; // import java.util.List; // //학생정보를 처리하는 Service 클래스가 반드시 상속받아야 되는 인터페이스 public interface StudentService { void addStudent(Student student); void modifyStudent(Student student); void removeStudent(int num); Student getStudent(int num); List<Student> getStudentList(); }
📃StudentServiceImpl.java(클래스)
※ xyz.itwill05.di 패키지에 StudentServiceImpl.java 클래스 생성
package xyz.itwill05.di; // import java.util.List; // //Service 클래스 : 프로그램 실행에 필요한 데이터 처리 기능을 모듈화하여 제공하는 클래스 - 컴퍼넌트 //→ Service 클래스의 메소드는 DAO 클래스의 메소드를 호출하여 데이터 처리 기능 제공 - 모듈화 //→ DAO 클래스는 Service 클래스와 포함관계(의존관계)로 설정되도록 작성 //→ Service 클래스가 변경돼도 Service 클래스와 관계가 있는 클래스(모델 클래스)에 영향을 최소화하기 위해 인터페이스를 상속받아 작성 - 결합도를 낮춰 유지보수 효율성 증가 public class StudentServiceImpl implements StudentService { //StudentJdbcDAO 객체를 저장하기 위한 필드 //→ 필드에 StudentJdbcDAO 객체를 저장해야만 포함관계가 성립 //→ StudentServiceImpl 클래스의 메소드에서 StudentJdbcDAO 객체의 메소드 호출 가능 //문제점) DAO 클래스가 변경될 경우 Service 클래스의 필드 및 메소드 변경 //→ 결합도가 높아 유지보수 효율성 감소 //private StudentJdbcDAO studentJdbcDAO;//비권장 //해결법) DAO 클래스가 반드시 상속받아야 되는 인터페이스로 필드 선언 //→ 필드에는 인터페이스를 상속받은 모든 DAO 클래스의 객체 저장 가능 // //StudentDAO 인터페이스를 상속받은 모든 DAO 클래스의 객체를 저장할 수 있는 필드 //→ StudentDAO 인터페이스를 상속받은 DAO 클래스의 객체를 저장해야만 의존관계 성립 //→ Service 클래스의 메소드에서 필드로 메소드를 호출하면 필드에 저장된 자식 객체의 메소드 호출 - 오버라이딩에 의한 다형성 : 결합도를 낮춰 유지보수의 효율성 증가 //→ DAO 클래스가 변경돼도 Service 클래스의 영향 최소화 private StudentDAO studentDAO; // public StudentServiceImpl() { System.out.println("### StudentServiceImpl 클래스의 기본 생성자 호출 ###"); } public StudentServiceImpl(StudentDAO studentDAO) { super(); this.studentDAO = studentDAO; System.out.println("### StudentServiceImpl 클래스의 매개변수가 선언된 생성자 호출 ###"); } public StudentDAO getStudentDAO() { return studentDAO; } public void setStudentDAO(StudentDAO studentDAO) { this.studentDAO = studentDAO; System.out.println("*** StudentServiceImpl 클래스 setStudentDAO(StudentDAO studentDAO) 메소드 호출 ***"); } @Override public void addStudent(Student student) { System.out.println("*** StudentServiceImpl 클래스 addStudent(Student student) 메소드 호출 ***"); studentDAO.insertStudent(student); } @Override public void modifyStudent(Student student) { System.out.println("*** StudentServiceImpl 클래스 modifyStudent(Student student) 메소드 호출 ***"); studentDAO.updateStudent(student); } @Override public void removeStudent(int num) { System.out.println("*** StudentServiceImpl 클래스 removeStudent(int num) 메소드 호출 ***"); studentDAO.deleteStudent(num); } @Override public Student getStudent(int num) { System.out.println("*** StudentServiceImpl 클래스 getStudent(int num) 메소드 호출 ***"); return studentDAO.selectStudent(num); } @Override public List<Student> getStudentList() { System.out.println("*** StudentServiceImpl 클래스 getStudentList() 메소드 호출 ***"); return studentDAO.selectStudentList(); } }
📃05-1_di.xml
※ src/main/resources 폴더에 05-1_di.xml에 코드 작성
<!-- Student 인터페이스를 상속받아 자식클래스를 Spring Bean으로 등록 --> <bean class="xyz.itwill05.di.StudentJdbcDAO" id="studentJdbcDAO"/> <bean class="xyz.itwill05.di.StudentMybatisDAO" id="studentMybatisDAO"/> <!-- --> <!-- StudentService 인터페이스를 상속받아 자식클래스를 Spring Bean으로 등록 --> <!-- → 클래스의 기본 생성자를 이용하여 객체 생성 - 객체 필드에는 기본값 저장 --> <!-- 문제점) StudentServiceImpl 클래스로 생성된 객체의 필드에는 [null]이 저장되어 StudentServiceImpl 클래스의 메소드에서 StudentDAO 클래스의 메소드를 호출하면 NullPointerExcetion 발생 - 의존관계 미성립 --> <!-- <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentServiceImpl"></bean> --> <!-- 해결법) StudentServiceImpl 클래스의 객체 필드에 StudentDAO 인터페이스를 상속받은 자식클래스의 객체가 저장되도록 설정 - 의존관계 성립 --> <!-- --> <!-- StudentServiceImpl 클래스의 매개변수가 선언된 생성자를 이용하여 객체 생성 --> <!-- → 생성자 매개변수에 StudentDAO 인터페이스를 상속받은 자식클래스의 객체 전달하여 필드에 저장 - Construction Injection --> <!-- constructor-arg 엘리먼트를 사용하여StudentServiceImpl 클래스의 객체 필드에 StudentDAO 인터페이스를 상속받은 자식클래스의 객체 저장 - 의존관계 성립 --> <!-- ref 속성 : 스프링 컨테이너로 관리되는 Spring Bean의 식별자를 속성값으로 설정 --> <!-- → 스프링 컨테이너로 관리되는 Spring Bean을 객체 필드에 저장 - 의존성 주입(DI : Dependency Injection) --> <!-- <bean class="xyz.itwill05.di.StudentServiceImpl"> <constructor-arg ref="studentJdbcDAO"/> </bean> --> <!-- --> <!-- StudentServiceImpl 클래스의 기본 생성자를 이용하여 객체를 생성 --> <!-- → Setter 메소드를 호출하여 객체 필드에 StudentDAO 인터페이스를 상속받은 자식 클래스의 객체를 필드에 저장 >> Setter Injection --> <!-- property 엘리먼트를 사용하여 StudentServiceImpl 클래스의 객체 필드에 StudentDAO 인터페이스를 상속받은 자식클래스의 객체 저장 - 의존관계 성립 --> <!-- <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentServiceImpl"> <property name="studentDAO" ref="studentJdbcDAO"></property> </bean> --> <!-- 기존에 사용하던 StudentJdbcDAO 클래스 대신 새롭게 작성한 StudentMybatisDAO 클래스로 의존관계를 변경하고자 할 경우 ref 속성값만 변경 --> <!-- 기존 클래스 대신 새로운 클래스로 바꿔도 관계가 설정된 클래스를 변경하지 않고 Spring Bean Configuration File만 수정해도 의존관계 변경 - 유지보수 효율성 증가 --> <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentServiceImpl"> <property name="studentDAO" ref="studentMybatisDAO"></property> </bean>
📃StudentApp.java(클래스)
※ xyz.itwill05.di 패키지에 StudentApp.java에 코드 작성
//프로그램 실행에 필요한 데이터 처리 기능은 Service 클래스의 메소드를 호출하여 사용 //→ 스프링 컨테이너에게 Service 클래스의 객체를 제공받아 메소드 호출 //StudentServiceImpl service=context.getBean("studentServiceImpl", StudentServiceImpl.class); // //클래스로 참조변수를 생성하여 객체를 반환받아 저장하는 것보다는 인터페이스로 참조변수를 생성하여 객체를 저장하는 것이 유지보수의 효율성 증가 //→ 인터페이스로 반환받기 위한 객체의 형변환 가능 StudentService service=context.getBean("studentServiceImpl", StudentServiceImpl.class); // service.addStudent(student1); service.modifyStudent(student1); service.removeStudent(1000); service.getStudent(100); service.getStudentList();
📃StudentMybatisDAO.java(클래스)
※ xyz.itwill05.di 패키지에 StudentMybatisDAO.java 클래스 생성
package xyz.itwill05.di; // import java.util.List; // public class StudentMybatisDAO implements StudentDAO { public StudentMybatisDAO() { System.out.println("### StudentMybatisDAO 클래스의 기본 생성자 호출 ###"); } @Override public int insertStudent(Student student) { System.out.println("*** StudentMybatisDAO 클래스 insertStudent(Student student) 메소드 호출 ***"); return 0; } @Override public int updateStudent(Student student) { System.out.println("*** StudentMybatisDAO 클래스 updateStudent(Student student) 메소드 호출 ***"); return 0; } @Override public int deleteStudent(int num) { System.out.println("*** StudentMybatisDAO 클래스 deleteStudent(int num) 메소드 호출 ***"); return 0; } @Override public Student selectStudent(int num) { System.out.println("*** StudentMybatisDAO 클래스 selectStudent(int num) 메소드 호출 ***"); return null; } @Override public List<Student> selectStudentList() { System.out.println("*** StudentMybatisDAO 클래스 selectStudentList() 메소드 호출 ***"); return null; } }