티스토리 뷰

초보 웹 개발자를 위한 스프링 5 프로그램 입문을 보고 복습 겸 개인 학습 정리입니다. (windows 기준)

 

 

스프링의 특징

의존 주입 (DI) 지원

AOP (Aspect-Orignted Programing) 지원

MVC 제공

JDBC, JPA 연동 선언적 트랜젝션 DB 연동 지원

 

 

의존 (Dependency)

객체 간의 의존을 의미

한 클래스가 다른 클래스의 메서드를 실행할 때 이를 '의존'이라고 표현

의존은 변경에 의해 영향을 받는 관계를 의미

 

→ 기존 클래스 내부에서 직접 의존 객체를 생성하는 것이 쉬운 방법이지만 유지보수 관점에서 문제점을 유발할 수 있다.

 

그래서 Spring DI를 통한 의존 처리

DI이라는 방식을 이용하여 모듈 간의 결합도를 낮춘다.

대신 의존 객체를 전달받는 방식

의존 객체를 생성자를 통해 주입한다 <- 변경의 유연함

 

 

 

 

회원가입 및 수정 예제 프로젝트 만들기 (메이븐 기준)  예제 코드

sp5-chap03 프로젝트 폴더 생성

프로젝트(sp5-chap03) 하위 폴더로 src\main\java 생성

sp5-chap03 폴더 내부에 pom.xml 생성

 

※ 책에 나와있는 pom.xml파일은 메이븐 버전이 달라 프로그램이 실행이 안되니 현재 버전에 맞게 수정이 필요하다.

 

java 디렉토리에서 패키 지명을 spring으로 작성 후 클래스들을 만든다. 

 

→ sp5-chap03/src/main/java/spring/각 클래스 명 

회원 데이터 관련 클래스

- Member

- WrongIdPasswordException (패스워드 

- MemberDao (db 연결 대신 java map을 이용하여 만든 클래스)

회원 가입 처리 관련 클래스

- DuplicateMemberException

- RegisterRequest

- MemberRegisterService 

암호 변경 관련 클래스

- MemberNotFoundException

- ChangePasswordSecvice

 

객체 조립기 작성

객체 생성에 사용할 클래스를 변경하기 위해 객체를 주입하는 코드 한 곳만 변경하면 된다고 했다.

 

객체를 생성하고 의존 객체를 주입해주는 클래스를 작성하는 것.

의존 객체를 주입한다는 것은 서로 다른 두 객체를 조립한다고 생각할 수 있어 이 역할을 하는 것을 조립기 (assembler)라고 표현한다.

 

이 조립 키 클래스는 assembler 패키지를 따로 만들어 코드를 작성한다.

→ sp5-chap03/src/main/java/assembler/Assembler.java

package assembler;

import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberRegisterService;

public class Assembler {

	private MemberDao memberDao;
	private MemberRegisterService regSvc;
	private ChangePasswordService pwdSvc;
	//13~18행에서 객체에 대한 의존을 주입시킴
	public Assembler() {
		memberDao = new MemberDao(); // 만약 다른 클래스를 사용하려면 여기서 변경하면된다.
		regSvc = new MemberRegisterService(memberDao);
		pwdSvc = new ChangePasswordService();
		pwdSvc.setMemberDao(memberDao);
	}

	public MemberDao getMemberDao() {
		return memberDao;
	}

	public MemberRegisterService getMemberRegisterService() {
		return regSvc;
	}

	public ChangePasswordService getChangePasswordService() {
		return pwdSvc;
	}

}

 

메인 클래스 작성

 

메인 클래스는 명령어를 입력받고 각 명령어에 알맞은 기능을 수행하도록 구현되어있다.

new : 새로운 회원 데이터 추가

change : 회원 데이터의 암호를 변경 

 

Main.java 38행

// 메인 클래스의 38행 발췌
private static Assembler assembler = new Assembler();

 

38행에서 Assembler 객체를 선언하고 생성했는데, 이때  Assembler 클래스의 생성자에서 필요한 객체를 생성하고 의존을 주입한다.

 

따라서 38행에서 Assembler 객체를 생성하는 시점에 사용할 객체가 모두 생성된다.

 

package main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import assembler.Assembler;
import spring.ChangePasswordService;
import spring.DuplicateMemberException;
import spring.MemberNotFoundException;
import spring.MemberRegisterService;
import spring.RegisterRequest;
import spring.WrongIdPasswordException;

public class MainForAssembler {

	public static void main(String[] args) throws IOException {
		// BufferedReader (== Scanner) System.in이니까 프로그램에서 사용자로부터 입력받기 위해 초기화
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		while (true) { // while 문이라 exit입력하기 전까지 계속 실행됨
			System.out.println("명령어를 입력하세요:");
			String command = reader.readLine(); //위 19행에서 초기화했으니까 여기서 입력받음
			if (command.equalsIgnoreCase("exit")) {	//사용자가 exit입력하면 종료됨
				System.out.println("종료합니다.");
				break;
			}
			if (command.startsWith("new ")) { //입력한 문자열이 NEW로 시작되면 processNewCommand() 실행 "new"뒤에 공백문자가 있음
				processNewCommand(command.split(" ")); // 이 command.split(" ") 코드는 command값이 "new a@a.com 이름 암호 암호"라면
				continue;									 // command.split(" ") -> {"new", "a@a.com", "이름", "암호", "암호"} 이런 결과를 만들어 processNewCommand 전달한다.
			} else if (command.startsWith("change ")) { //입력한 문자열이 change로 시작되면 processChangeCommand() 실행 "change로"뒤에 공백문자가 있음
				processChangeCommand(command.split(" "));
				continue;
			}
			printHelp(); //명령어를 잘못 입력한 경우 도움말 출력해주는 메서드 실행됨 
		}
	}
	//assembler 객체 생성
	private static Assembler assembler = new Assembler();

	private static void processNewCommand(String[] arg) {
		if (arg.length != 5) {
			printHelp();
			return;
		}	
        //Assembler.java에서 이미 의존을 주입했고 38행에서 Assembler를 생성했기 때문에 사용할 수 있다.
		MemberRegisterService regSvc = assembler.getMemberRegisterService();
		RegisterRequest req = new RegisterRequest();
		req.setEmail(arg[1]);
		req.setName(arg[2]);
		req.setPassword(arg[3]);
		req.setConfirmPassword(arg[4]);
		
		if (!req.isPasswordEqualToConfirmPassword()) {
			System.out.println("암호와 확인이 일치하지 않습니다.\n");
			return;
		}
		try {
			regSvc.regist(req);
			System.out.println("등록했습니다.\n");
		} catch (DuplicateMemberException e) {
			System.out.println("이미 존재하는 이메일입니다.\n");
		}
	}

	private static void processChangeCommand(String[] arg) {
		if (arg.length != 4) {
			printHelp();
			return;
		}
		ChangePasswordService changePwdSvc = 
				assembler.getChangePasswordService();
		try {
			changePwdSvc.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();
	}
}

 

 

[Run As] → [Java Application] 누르면 이클립스 콘솔 뷰에 아래와 같이 출력되면 잘 작성한 것

 

 

 

스프링 DI설정

스프링을 사용하지 않고 Assembler 클래스를 만들어 의존 주입을 이용했다면 스프링을 사용하는 코드를 작성해보자.

@Configuration 애너테이션과 @Bean 애너테이션을 붙이고 설정 클래스를 이용하여 컨테이너를 생성해야 한다.

config 패키지에 AppCtx 클래스 생성

→ sp5-chap03/src/main/java/config/AppCtx.java

package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberRegisterService;
//@Configuration은 스프링 설정 클래스를 의미함 이 애노테이션을 붙여야 스프링 설정 클래스로 사용할 수 있다.
@Configuration
public class AppCtx {
    // @Bean 애노테이션은 해당 메서드가 생성한 객체를 스프링 빈이라고 설정한다.
    @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;
    }
}

 

@Configuration

스프링 설정 클래스를 의미하며, 이 애노테이션을 붙여야 스프링 설정 클래스로 사용할 수 있다.

 

@Bean

해당 메서드가 생성한 객체를 스프링 빈이라고 설정한다

빈 애노테이션을 붙인 각각의 메서드마다 한 개의 빈 객체 생성

이때 메서드 이름을 빈 객체의 이름으로 사용한다.

getBean() 메서드를 이용해서 사용할 객체를 구할 수 있다.

 

 

위 설정 클래스를 만들고 난 뒤, 객체를 생성하고 의존 객체를 주입하는 것은 스프링 컨테이너이므로 설정 클래스를 이용해서 컨테이너를 생성해야 한다.

 

책 2장에서 사용한 AnnotationConfigApplicationContext 클래스를 이용해서 스프링 컨테이너를 생성할 수 있다.

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);

 

다음으로 스프링 컨테이너를 생성하면 getBean() 메서드를 이용해서 사용할 객체를 구할 수 있다.

// 컨테이너에서 이름이 memberRegSvc인 빈 객체를 구한다.
MemberRegisterService regSvc = ctx.getBean("memberRegSvc", MemberRegisterService.class);

스프링 컨테이너인 ctx로부터 이름이 "memberRegSvc"인 빈 객체를 구한다.

 

 

 

 

DI 방식 1 : 생성자 방식 - 빈 객체를 생성하는 시점에 모든 의존 객체가 주입된다.

 

spring 패키지의 MemberRegisterService 클래스의 코드를 보면 생성자를 통해 의존 객체를 주입받아 필드(this.memberDao)에 할당했다.

 

※ 생성자에 전달할 의존 객체가 두 개 이상이어도 동일한 방식으로 주입하면 된다.

package spring;

import java.time.LocalDateTime;

public class MemberRegisterService {
	private MemberDao memberDao;
	// 생성자를 통해 의존 객체를 주입 받음
	public MemberRegisterService(MemberDao memberDao) {
		this.memberDao = memberDao;
	}
	
	public Long regist(RegisterRequest req) { //주입 받은 의존 객체의 메서드를 사용
		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();
	}
}

 

그리고 config 패키지에 AppCtx 클래스에서 생성자를 이용해서 의존 객체를 주입하기 위해 해당 설정을 담은 메서드를 호출했다.

 

→ sp5-chap03/src/main/java/config/AppCtx.java 

public class AppCtx {
    // @Bean 애노테이션은 해당 메서드가 생성한 객체를 스프링 빈이라고 설정
    @Bean // 이 빈은 각각의 빈 객체를 생성 
    public MemberDao memberDao() {
        return new MemberDao();
    }

    @Bean
    public MemberRegisterService memberRegSvc() {
        return new MemberRegisterService(memberDao());
    }
    
    ...이하 생략

 

AppCtx 클래스에 세터 메서드 방식을 사용하는 설정을 추가했으므로, MainForSpring 코드에 MemberInfoPrinter 클래스를 사용하는 코드를 추가한다.

→ sp5-chap03/src/main/java/main/MainForSpring .java

 

package main;
... 생략
import spring.MemberListPrinter;
... 생략
public class MainForSpring {

	private static ApplicationContext ctx = null;
	// AnnotationConfigApplicationContext 사용해서 스프링 컨테이너 생성, 객체 생성하고 의존 객체 주입
	public static void main(String[] args) throws IOException { 
    //설정파일 AppCtx클래스로 부터 생성할 객체와 의존 주입 대상을 정함
		ctx = new AnnotationConfigApplicationContext(AppCtx.class);
		
		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;
			}
			if (command.startsWith("new ")) {
				processNewCommand(command.split(" "));
				continue;
			} else if (command.startsWith("change ")) {
				processChangeCommand(command.split(" "));
				continue;
			} // 추가 회원 list를 볼수 있는 명령어 추가 
			else if (command.equals("list")) {
				processListCommand();
				continue;
            }
            printHelp();
		}
	}   // list를 볼 수 있는 메서드 추가
    	private static void processListCommand() {
		MemberListPrinter listPrinter = 
			ctx.getBean("listPrinter", MemberListPrinter.class);
		listPrinter.printAll();
        
        ... 생략

 

 

[Run As] → [Java Application]

추가한 명령어 list를 입력하면 입력한 회원의 정보가 출력되는 것을 확인할 수 있다.

 

명령어 list의 실행 결과 화면

 

 

 

DI 방식 2 : 세터 메서드 방식 - 세터 메서드 이름을 통해 어떤 의존 객체가 주입되는지 알 수 있다.

생성자 외 세터 메서드(get 게터와 set 세터.. )를 이용해서 객체를 주입받기도 한다.

메서드는 자바빈 규칙에 따라 작성한다.

 

- 메서드 이름은 set으로 시작

- set 뒤에 첫 글자는 대문자로 시작

- 파라미터 1개

- 리턴 타입 void

회원 정보를 보기 위한 추가 클래스 작성한다.

 

spring패키지에 MemberInfoPrinter클래스 생성

→ sp5-chap03/src/main/java/spring/MemberInfoPrinter.java

 

18행~24행~ 에 사용된 이 세터 메서드MemberDao 타입의 객체와 아래 MemberPrinter 타입의 객체에 대한 의존을 주입하기 위해 사용되었다.

package spring;

public class MemberInfoPrinter {
	private MemberDao memDao;
	private MemberPrinter printer;
	
	public void printMemberInfo(String email) {
		Member member = memDao.selectByEmail(email);
		if (member == null) {
			System.out.println("데이터 없음");
			return;
		}
		printer.print(member);
		System.out.println();
	}
   // 두 개의 세터 메서드 정의 
     // 이 세터 메서드는 MemberDao 타입의 객체와 아래
     // MemberPrinter 타입의 객체에 대한 의존을 주입하기위해 사용됨
	public void setMemberDao(MemberDao memberDao) {
		this.memDao = memberDao;
	}
	public void setPrinter(MemberPrinter printer) {
		this.printer = printer;
	}
	
}

 

config 패키지에 AppCtx 클래스에 @Bean 객체를 추가한다

→ sp5-chap03/src/main/java/config/AppCtx.java

 

추가된 infoPrinter() 빈은 세터 메서드를 이용해서 memberDao 빈과 memberPrinter 빈을 주입한다.

    // DI 세터 메서드 추가 기입
    @Bean
    public MemberInfoPrinter infoPrinter() {
    	MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
    	infoPrinter.setMemberDao(memberDao());
    	infoPrinter.setPrinter(memberPrinter());
    	return infoPrinter;
    }

 

AppCtx 클래스에 세터 메서드 방식을 사용하는 설정을 추가했으므로, MainForSpring 코드에 MemberInfoPrinter 클래스를 사용하는 코드를 추가한다.

 

기존 명령어 new, change 외 list, info를 추가하였다.

 

→ sp5-chap03/src/main/java/main/MainForSpring. java

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;
			}
			if (command.startsWith("new ")) {
				processNewCommand(command.split(" "));
				continue;
			} else if (command.startsWith("change ")) {
				processChangeCommand(command.split(" "));
				continue;
			} // 추가 회원 list를 볼수 있는 명령어 추가 
			else if (command.equals("list")) {
				processListCommand();
				continue;
			} // DI 세터 방식 info 명령어 추가
			else if (command.startsWith("info ")) {
				processInfoCommand(command.split(" "));
				continue;
			}
            
            
            ... 생략
            
     // 추가 회원 list를 볼수 있는 메서드
	private static void processListCommand() {
		MemberListPrinter listPrinter = 
			ctx.getBean("listPrinter", MemberListPrinter.class);
		listPrinter.printAll();
	}// DI 세터 방식 info 명령어 추가
	private static void processInfoCommand(String[] arg) {
		if (arg.length !=2) {
			printHelp();
			return;
		}
		MemberInfoPrinter infoPrinter = ctx.getBean("infoPrinter", MemberInfoPrinter.class);
		infoPrinter.printMemberInfo(arg[1]);
	}

 

 

[Run As] → [Java Application]

DI방식 1에서 추가한 list와 DI방식 2에서 추가한 info 명령어를 입력하면 입력한 회원의 정보가 출력되는 것을 확인할 수 있다.

 

세터를 이용해서 의존 객체를 주입 받은 infoPrinter 빈의 실행 결과

 

 

 

DI방식 장점을 정리하면,

생성자 방식 : 빈 객체를 생성하는 시점에 모든 의존 객체가 주입된다.

설정 메서드 방식 : 세터 메서드 이름을 통해 어떤 의존 객체가 주입되는지 알 수 있다.

 

 

기본 데이터 타입 값 설정

추가로 이 프로그램? 의 버전을 알 수 있는 명령어를 추가해보도록 하자.

 

 

새로운 VersionPrinter 클래스를 작성한다.

단 아래 코드는 두 개의 int 타입 값을 세터 메서드로 전달받는다.

→ sp5-chap03/src/main/java/spring/VersionPrinter. java

package spring;

public class VersionPrinter {
	private int majorVersion;
	private int minorVersion;
	
	public void print() {
		System.out.printf("이 프로그램의 버전은 %d.%d입니다. \n\n", majorVersion,minorVersion);
	}			// int 타입 값을 세터 메서드로 전달 받음
	public void setMajorVersion(int majorVersion) {
		this.majorVersion = majorVersion;
	}			// int 타입 값을 세터 메서드로 전달 받음
	public void setMinorVersion(int minorVersion) {
		this.minorVersion = minorVersion;
	}
}

 

config 패키지에 AppCtx 클래스에 @Bean 객체를 추가한다

→ sp5-chap03/src/main/java/config/AppCtx.java

    // 기본 버전 타입값 추가 기입
    @Bean
    public VersionPrinter versionPrinter() {
    	VersionPrinter versionPrinter = new VersionPrinter();
    	versionPrinter.setMajorVersion(5);
    	versionPrinter.setMinorVersion(0);
    	return versionPrinter;
    }

 

 

AppCtx 클래스에 빈 객체를 추가했으므로 MainForSpring 코드에 VersionPrinter 관련 코드를 추가한다.

→ sp5-chap03/src/main/java/main/MainForSpring. java

 

		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;
			}
			if (command.startsWith("new ")) {
				processNewCommand(command.split(" "));
				continue;
			} else if (command.startsWith("change ")) {
				processChangeCommand(command.split(" "));
				continue;
			} // 추가 회원 list를 볼수 있는 명령어 추가 
			else if (command.equals("list")) {
				processListCommand();
				continue;
			} // DI 세터 방식 info 명령어 추가
			else if (command.startsWith("info ")) {
				processInfoCommand(command.split(" "));
				continue;
			} // 버전 명령어 추가
			else if (command.equals("version")) {
				processVersionCommand();
				continue;
			}
			printHelp();
		}
	}
	// 추가 회원 list를 볼수 있는 메서드
	private static void processListCommand() {
		MemberListPrinter listPrinter = 
			ctx.getBean("listPrinter", MemberListPrinter.class);
		listPrinter.printAll();
	}// DI 세터 방식 info 명령어 추가
	private static void processInfoCommand(String[] arg) {
		if (arg.length !=2) {
			printHelp();
			return;
		}
		MemberInfoPrinter infoPrinter = ctx.getBean("infoPrinter", MemberInfoPrinter.class);
		infoPrinter.printMemberInfo(arg[1]);
	}
	// 버전 명령어 추가
	private static void processVersionCommand() {
		VersionPrinter versionPrinter = ctx.getBean("versionPrinter", VersionPrinter.class);
		versionPrinter.print();
	}

 

[Run As] → [Java Application]

실행하면 Version 명령어에 대한 내용이 출력되는 것을 확인할 수 있다.

version 명령어 실행 결과 화면

 

 

☆ 두 개 이상의 설정 파일 사용하기 ☆ 

 

위에서 작성한 예제 외 실제로 스프링을 이용해서 개발하다 보면 많은 빈을 설정하게 된다.

설정하는 빈의 개수가 증가하면 한 개의 클래스 파일에 설정하는 것보다 영역별로 설정 파일을 나누면 관리하기 편해진다.

 

스프링은 한 개 이상의 설정 파일을 이용해서 컨테이너를 생성할 수 있는데, 

예제 파일을 두 개 만들어보자.

 

Config 패키지에 예제 파일을 2개 만들어 추가한다.

→ sp5-chap03/src/main/java/config/AppConf1.java

package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import spring.MemberDao;
import spring.MemberPrinter;

// 스프링 컨테이너 설정 애노테이션 
@Configuration
public class AppConf1 {
	
	@Bean
	public MemberDao memberDao() {
		return new MemberDao();
	}
	@Bean
	public MemberPrinter memberPrinter() {
		return new MemberPrinter();
	}

}

→ sp5-chap03/src/main/java/config/AppConf2.java

package config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import spring.ChangePasswordService;
import spring.MemberDao;
import spring.MemberInfoPrinter;
import spring.MemberListPrinter;
import spring.MemberRegisterService;
import spring.VersionPrinter;
import spring.MemberPrinter;

@Configuration
public class AppConf2 {
	@Autowired // 자동 주입 기능을 위한 것 MemberDao 타입의 빈을 memberDao 필드에 할당
	private MemberDao memberDao;
	@Autowired // 자동 주입 기능을 위한 것 MemberPrinter 타입의 빈을 memberPrinter 필드에 할당
	private MemberPrinter memberPrinter;
	
	@Bean
	public MemberRegisterService memberRegSvc() {
		return new MemberRegisterService(memberDao);
	}
	@Bean
	public ChangePasswordService changePwdSvc() {
		ChangePasswordService pwdSvc = new ChangePasswordService();
		pwdSvc.setMemberDao(memberDao);
		return pwdSvc;
	}
	@Bean
	public MemberListPrinter listPrinter() {
		return new MemberListPrinter(memberDao, memberPrinter);
	}
	@Bean
	public MemberInfoPrinter infoPrinter() {
		MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
		infoPrinter.setMemberDao(memberDao);
		infoPrinter.setPrinter(memberPrinter);
		return infoPrinter;
	}
	@Bean
	public VersionPrinter versionPrinter() {
		VersionPrinter versionPrinter = new VersionPrinter();
		versionPrinter.setMajorVersion(5);
		versionPrinter.setMinorVersion(0);
		return versionPrinter;
	}
}

 

@Autowired

자동 주입 기능을 위한 것. 의존 주입과 관련이 있다.

스프링 설정 클래스의 필드에 이 애노테이션을 붙이면 해당 타입의 빈을 찾아 필드에 할당한다.

 

위 코드의 경우 스프링 컨테이너는 MemberDao 타입의 빈을 memberDao 필드에 할당한다.

AppConf1 클래스의 MemberDao 타입의 빈을 설정했으므로 AppConf2 클래스의 memberDao 필드에는 AppConf1 클래스에서 설정한 빈이 할당된다..

 

 

 

 

 

 

 

 

 

 

<- 어렵다.. chap 4장에서 ㅠㅠ 계속 

'study > Spring' 카테고리의 다른 글

chap 07 - AOP 프로그래밍  (0) 2023.01.10
chap 06 - 빈 라이프사이클 & 범위  (0) 2023.01.09
chap 05 - 컴포넌트 스캔  (0) 2023.01.05
chap 04 - 의존 자동 주입  (0) 2023.01.04
환경 변수 설정 (windows 기준으로 설치)  (0) 2022.11.29
댓글