본문 바로가기
학습/SPRING

03. 스프링 DI - 애노테이션 방식, XML 방식

by Elfen Lied 2022. 12. 19.
반응형

- 정리


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

댓글