- 정리
1. 의존(Dependency)
- DI,Dependency Injection (의존 주입)
- MemberService, MemberDao
- MemberService는 MemberDao의 메서드를 사용한다.
- MemberService는 MemberDao에 의존한다.
2. 예제코드
- 프로젝트 생성 : chap03(다이나믹 웹프로젝트->메이븐 프로젝트)
- pom.xml : spring-context 의존성 추가
- 클래스 :
- spring.Member
- spring.WrongIdPasswordException
- spring.RegisterRequest
- spring.MemberDao
- spring.MemberRegisterService
- spring.DuplicateMemberException
- spring.ChangePasswordService
- spring.MemberNotFoundException
3. 조립기 사용
ㅡ main.MainForAssembler
4. 애노테이션 설정 사용
- config.AppCtx
- main.MainForSpring
- AnnotationConfigApplicationContext객체로 AppCtx 설정 로딩
5. XML 설정 사용
- src/main/resources/appCtx.xml
- main.MainForSpring
- GenericXmlApplicationContext객체로 appCtx.xml설정 로딩
- pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.22.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
- spring 패키지 MemberRegisterService, MemberDao, RegisterRequest 클래스 생성
- MemberDao
package spring;
import java.util.HashMap;
import java.util.Map;
public class MemberDao {
private static long newxtId = 0; // 시퀀스
private Map<String, Member> map = new HashMap<>(); // 데이터베이스 테이블
public Member selectByEmail(String email) {
return null;
}
public void insert(Member newMember) {
}
}
Member클래스가 없기 때문에 빨간 줄이 뜬다. ctrl + 1 눌러서 만들어준다.
Member 클래스를 만들어준다.
DuplicateMemberException 클래스도 만들어줌
실행 예외기때문에 클래스 extend Exception으로 되어 있는것을 RuntimeException 으로 바꿔준다.
- DuplicateMemberException
package spring;
public class DuplicateMemberException extends RuntimeException {
public DuplicateMemberException(String message) {
super(message);
}
}
- Member
package spring;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
@Getter
public class Member {
@Setter // 필요한것만 선택할 경우 - 여기선 id
private Long id;
private String email;
private String password;
private String name;
private LocalDateTime registerDateTime;
public Member(String email, String password, String name, LocalDateTime registerDateTime) {
this.email = email;
this.password = password;
this.name = name;
this.registerDateTime = registerDateTime;
}
public void changePassword(String oldPwd, String newPwd) {
if(!this.password.equals(oldPwd)) { // 기존의 비밀번호가 일치하지 않으면
throw new WrongIdPasswordException(); // '잘못된비밀번호' 예외발생
}
this.password = newPwd; // 비밀번호 변경
}
}
WrongIdPasswordException 예외 클래스 생성
RuntimeException으로 고치기
- MemberRegisterService
package spring;
import java.time.LocalDateTime;
public class MemberRegisterService {
private MemberDao memberDao;
public MemberRegisterService() {
memberDao = new MemberDao();
}
public Long register(RegisterRequest req) { // RegisterRequest : 사용자가 입력한것
// 이메일로 회원 데이터 조회
Member member = memberDao.selectByEmail(req.getEmail());
if(member != null) { // 사용자가 입력한 이메일이 있다면
throw new DuplicateMemberException("dup email : " + req.getEmail());
}
// 사용자가 입력한 이메일이 없다면
Member newMember = new Member(
req.getEmail(),
req.getPassword(),
req.getName(),
LocalDateTime.now());
memberDao.insert(newMember);
return newMember.getId();
}
}
- RegisterRequest
package spring;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RegisterRequest { // MemberDTO와 같다 : 사용자가 입력한 값을 그대로 매칭 시킴
private String email;
private String password;
private String confirmPassword;
private String name;
}
- ChangePasswordService
package spring;
public class ChangePasswordService {
private MemberDao memberDao;
// 세터(수정자) 주입
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public void changePassword(String email, String oldPwd, String newPwd) {
Member member = memberDao.selectByEmail(email);
if(member == null) { // 회원을 찾을 수 없다면
throw new MemberNotFoundException(); // '회원찾을수없음' 예외발생
}
// 회원이 있다면
member.changePassword(oldPwd, newPwd); // 비밀번호 변경
memberDao.update(member); // 업데이트
}
}
MemberNotFoundException 예외 클래스 생성
RuntimeException으로 고치기
- MemberNotFoundException
package spring;
public class MemberNotFoundException extends RuntimeException {
}
- 객체 조립기 ( Assembler )
- assempler 패키지 Assembler 클래스 생성
- Assembler
스프링의 역할을 하는중
package assembler;
import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberRegisterService;
public class Assembler {
private MemberDao memberDao;
private MemberRegisterService regSvc;
private ChangePasswordService pwdSvc;
public Assembler() {
memberDao = new MemberDao(); // MemberDao객체생성
regSvc = new MemberRegisterService(memberDao); // MemberRegisterService객체생성, 생성자 주입
pwdSvc = new ChangePasswordService(); // ChangePasswordService객체생성
pwdSvc.setMemberDao(memberDao); // 세터주입
}
// 빈 검색기능
public MemberDao getMemberDao() {
return memberDao;
}
public MemberRegisterService getRegSvc() {
return regSvc;
}
public ChangePasswordService getPwdSvc() {
return pwdSvc;
}
}
- main 패키지 MainForAssembler 클래스 생성
- MainForAssembler
package main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import assembler.Assembler;
import spring.ChangePasswordService;
import spring.DuplicateMemberException;
import spring.MemberRegisterService;
import spring.RegisterRequest;
public class MainForAssembler {
private static Assembler assembler = new Assembler();
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("명령어를 입력하세요");
String command = reader.readLine(); // 예외는 던지기
if(command.equalsIgnoreCase("exit")) {
System.out.println("프로그램이 종료됩니다");
break;
} else if(command.startsWith("new ")) { // 회원가입
processNewCommand(command.split(" "));
} else if(command.startsWith("change ")) { // 비밀번호 변경
processChangeCommand(command.split(" "));
}
else {
printHelp(); // 사용법
}
}
}
private static void processNewCommand(String[] arg) { // 회원가입
if(arg.length != 5) {
printHelp();
return;
}
// {new, 이메일, 이름, 암호, 암호확인}
RegisterRequest req = new RegisterRequest();
req.setEmail(arg[1]);
req.setName(arg[2]);
req.setPassword(arg[3]);
req.setConfirmPassword(arg[4]);
// 어셈블러 컨테이너에서 MemberRegisterService 객체를 가져옴
MemberRegisterService regSvc = assembler.getRegSvc();
// 비밀번호 일치 확인
if(!req.isPasswordEqualToConfirmPassword()) { // 암호와 암호확인이 일치하면
System.out.println("암호와 암호확인이 일치하지 않습니다");
return;
}
try {
regSvc.register(req);
System.out.println("등록했습니다.\n");
} catch (DuplicateMemberException e) {
System.out.println("이미 존재하는 이메일입니다");
}
}
private static void processChangeCommand(String[] arg) { // 비밀번호 변경
if(arg.length != 4) {
printHelp();
return;
}
// {change, 이메일, 현재비번, 변경비번}
// 어셈블러 컨테이너에서 ChangePasswordService 객체를 가져옴
ChangePasswordService pwdSvc = assembler.getPwdSvc();
}
private static void printHelp() { // 사용법
System.out.println();
System.out.println("잘못된 명령입니다. 아래 명령어 사용법을 확인하세요");
System.out.println("명령어 사용법 : ");
System.out.println("new 이메일 이름 암호 암호확인");
System.out.println("change 이메일 현재비번 변경비번");
System.out.println();
}
}
콘솔에서 실행
- 스프링으로 사용
- 애노테이션 방식
- config 패키지 AppCtx 클래스 생성
- AppCtx
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberRegisterService;
@Configuration
public class AppCtx {
@Bean
public MemberDao memberDao() {
return new MemberDao();
}
@Bean
public MemberRegisterService memberRegSvc() {
return new MemberRegisterService(memberDao()); // 생성자 주입
}
@Bean
public ChangePasswordService changePwdSvc() {
ChangePasswordService pwdSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
}
- main 패키지 MainForSpring 클래스 생성
MainForAssembler를 복사해서 수정한다.
- MainForSpring
package main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import assembler.Assembler;
import config.AppCtx;
import spring.ChangePasswordService;
import spring.DuplicateMemberException;
import spring.MemberNotFoundException;
import spring.MemberRegisterService;
import spring.RegisterRequest;
import spring.WrongIdPasswordException;
public class MainForSpring {
// 애노테이션 방식, XML 방식 두가지 다 사용하기 위해서 선언함
// 애노테이션 방식만 쓸거면 작성할 필요없음
private static ApplicationContext ctx = null;
public static void main(String[] args) throws IOException {
// 애노테이션 방식
ctx = new AnnotationConfigApplicationContext(AppCtx.class);
// XML 방식
// ctx = new GenericXmlApplicationContext("classpath:appCtx.xml");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("명령어를 입력하세요");
String command = reader.readLine(); // 예외는 던지기
if(command.equalsIgnoreCase("exit")) {
System.out.println("프로그램이 종료됩니다");
break;
} else if(command.startsWith("new ")) { // 회원가입
processNewCommand(command.split(" "));
} else if(command.startsWith("change ")) { // 비밀번호 변경
processChangeCommand(command.split(" "));
}
else {
printHelp(); // 사용법
}
}
}
private static void processNewCommand(String[] arg) { // 회원가입
if(arg.length != 5) {
printHelp();
return;
}
// {new, 이메일, 이름, 암호, 암호확인}
RegisterRequest req = new RegisterRequest();
req.setEmail(arg[1]);
req.setName(arg[2]);
req.setPassword(arg[3]);
req.setConfirmPassword(arg[4]);
// 스프링 컨테이너에서 MemberRegisterService 객체를 가져옴
MemberRegisterService regSvc = ctx.getBean("memberRegSvc", MemberRegisterService.class);
// 비밀번호 일치 확인
if(!req.isPasswordEqualToConfirmPassword()) { // 암호와 암호확인이 일치하면
System.out.println("암호와 암호확인이 일치하지 않습니다");
return;
}
try {
regSvc.register(req);
System.out.println("등록했습니다.\n");
} catch (DuplicateMemberException e) {
System.out.println("이미 존재하는 이메일입니다");
}
}
private static void processChangeCommand(String[] arg) { // 비밀번호 변경
if(arg.length != 4) {
printHelp();
return;
}
// {change, 이메일, 현재비번, 변경비번}
// 어셈블러 컨테이너에서 ChangePasswordService 객체를 가져옴
ChangePasswordService pwdSvc = ctx.getBean("changePwdSvc", ChangePasswordService.class);
try {
pwdSvc.changePassword(arg[1], arg[2], arg[3]);
System.out.println("암호를 변경했습니다.\n");
} catch (MemberNotFoundException e) {
System.out.println("이메일이 존재하지 않습니다.\n");
} catch (WrongIdPasswordException e) {
System.out.println("이메일과 암호가 일치하지 않습니다.\n");
}
}
private static void printHelp() { // 사용법
System.out.println();
System.out.println("잘못된 명령입니다. 아래 명령어 사용법을 확인하세요");
System.out.println("명령어 사용법 : ");
System.out.println("new 이메일 이름 암호 암호확인");
System.out.println("change 이메일 현재비번 변경비번");
System.out.println();
}
}
문제없이 실행되면 됨.
- XML 방식
- src / main / resources 폴더 만들고 메이븐 업데이트한 뒤
ctrl + n 에서 spring 으로 검색한다음 appCtx.xml 생성해준다
- appCtx.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">
<bean id="memberDao" class="spring.MemberDao" />
<bean id="memberRegSvc" class="spring.MemberRegisterService">
<constructor-arg ref="memberDao" />
</bean>
<bean id="changePwdSvc" class="spring.ChangePasswordService">
<property name="memberDao" ref="memberDao" />
</bean>
</beans>
- MainForSpring 상단에 있는 코드 수정
public static void main(String[] args) throws IOException {
// 애노테이션 방식
// ctx = new AnnotationConfigApplicationContext(AppCtx.class);
// XML 방식
ctx = new GenericXmlApplicationContext("classpath:appCtx.xml");
`
`
`
`
`
`
`
실행해서 똑같이 되면 됨.
'학습 > SPRING' 카테고리의 다른 글
13. 스프링 - Paging (0) | 2022.12.30 |
---|---|
07. 스프링 - 의존 자동 주입 (0) | 2022.12.22 |
06. 스프링 - 두 개 이상의 설정 파일 사용하기 (0) | 2022.12.21 |
04. 스프링 DI : 생성자 방식 (0) | 2022.12.21 |
01~02 스프링 시작하기 (0) | 2022.12.19 |
댓글