스마트폰 연락처의 개요
스마트폰 연락처 프로젝트
스마트폰의 연락처로 특정 인물에 대한 연락처가 출력되는 프로그램
▶ 시나리오
① 연락처 3개의 샘플 데이터를 데이터베이스에 등록한다.
② 전체 연락처 정보를 출력한다.
③ 특정 인물에 대한 연락처를 출력한다.
▶ 프로그램 흐름도
MainClass | ContactRegisterService ContactSearchService |
ContactDao |
IoC 컨테이너 생성 | 연락처 등록 연락처 조회 |
연락처 등록, 조회 |
▶ 클래스와 appCtx.xml 내용
MainClass 클래스 | |
MainClass | main() 메서드가 명시되어 있는 클래스 |
Service 클래스 | |
ContactRegisterService | 연락처 등록 |
ContactSearchService | 연락처 조회 |
DAO 클래스 | |
ContactDao | DAO |
ContactSet | 연락처 1개 정보 |
Util 서비스 | |
InitSampleData | 샘플 데이터 초기화 |
IoC 컨테이너 | |
appCtx.xml | 객체 생성과 조립 |
· 연락처를 등록, 조회하는 ○○○Service 클래스들이 있고 이러한 ○○○Service는 DAO(WordDao)를 이용해서 연락처 정보를 관리한다.
· IcC 컨테이너 설정은 appCtx.xml이 한다.
· IoC 컨테이너 역할
- Service 객체를 생성
- Service가 생성될 때 필요한 DAO 객체를 생성하여 Service에 주입
의존 객체 자동 주입을 통해 Service에 DAO객체가 자동으로 주입되는 방법을 알아본다!
스마트폰 연락처 만들기
다음과 같이 자바 프로젝트 ch05_pjt_01에 패키지와 클래스 파일을 만든다.
이제 각각의 class의 코드를 살펴본다.
1. ContactSet 클래스
· 연락처 정보를 담고 있다.
· name 필드 : 연락처 이름
· phoneNumber 필드 : 전화번호
· 생성자에서 필드 초기화에 필요한 모든 값을 받는다.
· 모든 필드에 대한 getter와 setter 메서드가 있다.
package ch05_pjt_01.contact;
public class ContactSet {
private String name;
private String phoneNumber;
public ContactSet(String name, String phoneNumber) {
this.name = name;
this.phoneNumber = phoneNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
2. ContactDao 클래스
· 데이터베이스에 접속하고, Service에 의해서 호출된다.
· 데이터의 insert, search 기능을 수행한다.
· HashMap을 이용해서 데이터를 관리한다. (contactDB 필드에 단어 정보가 저장)
· key : 연락처 정보(ContactSet 클래스)에서 고윳값으로 부여되는 name / 특정 연락처 정보 조회시 사용
package ch05_pjt_01.contact.dao;
import java.util.HashMap;
import java.util.Map;
import ch05_pjt_01.contact.ContactSet;
public class ContactDao {
private Map<String, ContactSet> contactDB = new HashMap<String, ContactSet>();
public void insert(ContactSet contactSet) {
contactDB.put(contactSet.getName(), contactSet);
}
public ContactSet select(String name) {
return contactDB.get(name);
}
public Map<String, ContactSet> getContactDB(){
return contactDB;
}
}
3. ContactRegisterService 클래스
· 연락처 정보를 데이터베이스(지금은 Hashmap)에 저장하는 기능
· 생성자에서 DAO객체(ContactDao)를 받아서 contactDao 필드를 초기화하는 코드
· IoC 컨테이너에서 생성자에 ContactDao를 주입한다.
· verity() : 연락처를 등록하기 전에 name을 이용해서 기존에 등록된 연락처인지 판단
package ch05_pjt_01.contact.service;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactRegisterService {
private ContactDao contactDao;
public ContactRegisterService(ContactDao contactDao) {
this.contactDao = contactDao;
}
public void register(ContactSet contactSet) {
String name = contactSet.getName();
if (verify(name)) {
contactDao.insert(contactSet);
} else {
System.out.println("The name has already registered.");
}
}
public boolean verify(String name) {
ContactSet contactSet = contactDao.select(name);
return contactSet == null ? true : false;
}
public void setWordDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
}
4. ContactSearchService 클래스
· 특정 연락처의 정보를 얻는다.
· ContactRegisterService와 마찬가지로 생성자에서 전달받은 DAO 객체를 contactDao 필드에 저장한다.
· serchContact() : DAO를 이용해서 데이터베이스에서 단어 정보를 가져온다.
package ch05_pjt_01.contact.service;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactSearchService {
private ContactDao contactDao;
public ContactSearchService(ContactDao contactDao) {
this.contactDao = contactDao;
}
public ContactSet searchContact(String name) {
if (verify(name)) {
return contactDao.select(name);
} else {
System.out.println("Contact information is avilable.");
}
return null;
}
public boolean verify(String name) {
ContactSet contactSet = contactDao.select(name);
return contactSet != null ? true : false;
}
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
}
5. InitSampleData 클래스
· 프로그램 실행에 필요한 샘플 데이터
· 실제 데이터는 appCtx.xml에서 설정한다.
package ch05_pjt_01.contact.utils;
public class InitSampleData {
private String[] names;
private String[] phoneNumbers;
public String[] getNames() {
return names;
}
public void setNames(String[] names) {
this.names = names;
}
public String[] getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(String[] phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
}
6. appCtx.xml
· src/main/resources → appCtx.xml 생성
· InitSampleData 빈을 생성하는 코드로 3개의 샘플 연락처를 이용한다.
· appCtx.xml에 DAO, Service, 빈을 생성하는 코드를 작성한다.
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="initSampleData" class="ch05_pjt_01.contact.utils.InitSampleData">
<property name="names">
<array>
<value>류현진</value>
<value>손흥민</value>
<value>김연경</value>
</array>
</property>
<property name="phoneNumbers">
<array>
<value>010-0000-1111</value>
<value>010-0000-2222</value>
<value>010-0000-3333</value>
</array>
</property>
</bean>
<bean id="contactDao" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService">
<constructor-arg ref="contactDao" />
</bean>
<bean id="searchService" class="ch05_pjt_01.contact.service.ContactSearchService">
<constructor-arg ref="contactDao" />
</bean>
</beans>
· registerService와 searchService는 <constructor-arg/>를 이용해서 생성자에 의존 객체(DAO)를 주입받는다.
자동 의존 객체 주입
· registerService와 searchService는 생성자에서 contactDao를 주입받는다.
· contactDao 의존 객체를 주입받기 위해서는 다음과 같이 코드를 정형화했었다.
<constructor-arg ref="contactDao" />
매번 <constructor-arg/> 또는 <property/>을 작성하는 것은 불편하므로 스프링의 '의존 객체 자동 주입' 기능을 이용하면 자동으로 의존 객체가 주입된다.
자동으로 의존 객체 주입하기
1. context 네임스페이스와 스키마 추가하기
<context:annotation-config />를 사용하기 위한 네임스페이스와 스키마를 appCtx.xml에 추가한다.
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
2. <context:annotation-config /> 추가
애너테이션(annotation)을 사용하기 위한 <context:annotation-config />를 추가한다.
IoC 컨테이너애 생성된 빈이 필요로 하는 곳에 DAO객체가 사용될 수 있게 해준다.
ContactRegisterService와 ContactSearchService는 ContactDao를 필요로 하므로 <constructor-arg ref="contactDao" /> 없이도 생성자에 ContactDao가 자동으로 주입된다.
<context:annotation-config/>
3. <constructor-arg> 제거
<constructor-arg>을 제거한다.
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService"/>
<bean id="searchService" class="ch05_pjt_01.contact.service.ContactSearchService"/>
⚠️에러 : The prefix "context" for element "context:annotation-config" is not bound
Description Resource Path Location Type
The prefix "context" for element "context:annotation-config" is not bound. appCtx.xml /ch05_pjt_01/src/main/resources line 10 Language Servers
💡이 문제는 일반적으로 context 네임스페이스가 포함되지 않기 때문에 발생한다.
beans코드에 다음 내용을 추가해준다.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
그리고 spring-context.xsd를 불러오는 코드에 http → https로 변경해준다.
https://www.springframework.org/schema/context/spring-context.xsd">
따라서 총 코드는 다음과 같다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
참고 사이트 :
"context:comComponent-scan" 또는 "context:annotation-config" 요소의 접두사 "context"가 바인딩되지 않았습니다. 스프링 오류
❓<context:annotation-config />는 어떻게 ContactDao를 필요로 하는 곳에 자동으로 객체를 주입할까?
💡 <context:annotation-config />는 데이터 타입을 보고 의존 객체를 자동으로 주입한다.
ContactRegisterService와 ContactSearchService 모두 생성자에서 ContactDao를 필요로 하기 때문에 <context:annotation-config/>는 ContactRegisterService와 ContactSearchService 빈을 생성할 때 IoC 컨테이너에서 ContactDao를 찾고 이를 ContactRegisterService와 ContactSerachService 생성자에 주입한다.
ContactDao 자동 주입 확인
1. pom.xml
MainClass 클래스를 작성하기 전에 메이븐 설정 파일을 수정해준다.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>spring5</groupId>
<artifactId>ch04_pjt_01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- spring-context 모듈 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
</dependencies>
<!-- 빌드 설정 -->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. MainClass 클래스
package ch05_pjt_01.contact;
import org.springframework.context.support.GenericXmlApplicationContext;
import ch05_pjt_01.contact.service.ContactRegisterService;
import ch05_pjt_01.contact.service.ContactSearchService;
import ch05_pjt_01.contact.utils.InitSampleData;
public class MainClass {
public static void main(String[] args) {
// IoC 컨테이너 생성
GenericXmlApplicationContext ctx =
new GenericXmlApplicationContext("classpath:appCtx.xml");
// 샘플 데이터
InitSampleData initSampleData =
ctx.getBean("initSampleData", InitSampleData.class);
String[] names = initSampleData.getNames();
String[] phoneNumbers = initSampleData.getPhoneNumbers();
// 데이터 등록
ContactRegisterService registerService =
ctx.getBean("registerService", ContactRegisterService.class);
for(int i = 0; i < names.length; i++) {
ContactSet contactSet = new ContactSet(names[i], phoneNumbers[i]);
registerService.register(contactSet);
}
// 데이터 조회
ContactSearchService searchService =
ctx.getBean("searchService", ContactSearchService.class);
ContactSet contactSet = searchService.searchContact("류현진");
System.out.println("name: " + contactSet.getName());
System.out.println("phoneNubmer: " + contactSet.getPhoneNumber());
System.out.println("------------------------------------");
contactSet = searchService.searchContact("손흥민");
System.out.println("name: " + contactSet.getName());
System.out.println("phoneNubmer: " + contactSet.getPhoneNumber());
System.out.println("------------------------------------");
contactSet = searchService.searchContact("김연경");
System.out.println("name: " + contactSet.getName());
System.out.println("phoneNubmer: " + contactSet.getPhoneNumber());
System.out.println("------------------------------------");
ctx.close();
}
}
3. 의존 객체 자동 주입 확인
· ContactRegisterService와 ContactSearchService의 생성자 내부에 contactDao를 출력하는 코드를 추가하여 동일한 ContactDao객체가 자동 주입되는지 확인해본다.
■ ContactRegisterService 생성자
public void setWordDao(ContactDao contactDao) {
System.out.println("contactDao: " + contactDao);
this.contactDao = contactDao;
}
■ ContactSearchService 생성자
public void setContactDao(ContactDao contactDao) {
System.out.println("contactDao: " + contactDao);
this.contactDao = contactDao;
}
'Spring & Springboot > 올인원 스프링 프레임워크' 카테고리의 다른 글
XML 파일을 Java 파일로 변경하기 (0) | 2023.09.20 |
---|---|
스마트폰 연락처 -2 (0) | 2023.09.19 |
학사 관리 시스템 -4 (0) | 2023.09.14 |
학사 관리 시스템 -3 (0) | 2023.09.14 |
학사 관리 시스템 -2 (0) | 2023.09.13 |