TIL(2022.04.07)

조지성·2022년 4월 7일
0

TIL

목록 보기
54/78
post-thumbnail

Chap 04 의존 자동 주입

@Autowired 애노테이션을 이용한 자동주입

  • 자동 주입 기능을 사용하면 스프링이 알아서 의존 객체를 찾아서 주입한다.
  • 의존 주입 기능은 의존을 주입할 대상에 @Autowired 애노테이션을 붙이면 된다.
package spring;

import org.springframework.beans.factory.annotation.Autowired;

public class ChangePasswordService {
	
	// 설정 클래스에서 의존 주입을 하지 않아도 된다.
	@Autowired
	private 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);
	}

	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}
	
	
}
package spring;

import org.springframework.beans.factory.annotation.Autowired;

public class MemberInfoPrinter {
	
	private MemberDao memberDao;
	private MemberPrinter memberPrinter;
	
	public void printMemberInfo(String email) {
		Member member = memberDao.selectByEmail(email);
		if(member == null) {
			System.out.println("������ ����\n");
			return;
		}
		memberPrinter.print(member);
		System.out.println();
	}

	//빈 객체의 메서드에 @Autowired 애노테이션을 붙이면 스프링은 해당 메서드를 호출한다.
	// 이때 메서드 파라미터 타입에 해당하는 빈 객체를 찾아 인자로 주입하낟.
	@Autowired
	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}

	@Autowired
	public void setMemberPrinter(MemberPrinter memberPrinter) {
		this.memberPrinter = memberPrinter;
	}
	
}
package spring;

import java.time.LocalDateTime;

import org.springframework.beans.factory.annotation.Autowired;

public class MemberRegisterService {
	
	@Autowired
	public 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();
	}
}
package spring;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;


public class MemberListPrinter {
	
	private MemberDao memberDao;
	private MemberPrinter printer;
	
	
	public void printAll() {
		Collection<Member> members = memberDao.selectAll();
		System.out.println(members);
		members.forEach(m->printer.print(m));
	}

	@Autowired
	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}

	@Autowired
	public void setPrinter(MemberPrinter printer) {
		this.printer = printer;
	}
	
	
}
package config;

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.MemberPrinter;
import spring.MemberRegisterService;
import spring.VersionPrinter;

@Configuration

public class AppCtx {
	@Bean
	public MemberDao memberDao() {
		return new MemberDao();
	}

	@Bean
	public MemberPrinter memberPrinter() {
		return new MemberPrinter();
	}
	
	@Bean
	public MemberRegisterService memberRegSvc() {
		return new MemberRegisterService();
	}
	
	//의존을 주입하지 않아도 스프링이 @Autowired가 붙인 필드에 해당 타입의 빈 객체를 찾아서 주입한다.
	@Bean
	public ChangePasswordService changePwdSvc() {
		return new ChangePasswordService();
	}
	
	
	@Bean
	public MemberListPrinter listPrinter() {
		return new MemberListPrinter();
	}
	
	
	@Bean
	public MemberInfoPrinter infoPrinter() {
		return new MemberInfoPrinter();
	}
	
	@Bean
	public VersionPrinter versionPrinter() {
		VersionPrinter versionPrinter = new VersionPrinter();
		versionPrinter.setMajorVersion(5);
		versionPrinter.setMinorVersion(0);
		return versionPrinter;
	}
}

일치하는 빈이 없는 경우

  • @Autowired하지않은 빈을 의존주입하려는 경우 에러가 발생한다. 예를들어 memberDao라는 빈을 만들어놓지 않은 상태에서 주입 받으려고하면 오류가 발생한다.
  • @Autowired로 MemberList클래스 타입의 인자를 주입받고 싶은데 빈에 MemberList빈이 2개이상이면 오류가 발생한다 따라서 @Qualifier를 사용하자

@Qualifier 애노테이션을 이용한 의존 객체 주입

  • @Qualifier 애노테이션을 이용하면 자동 주입 대상 빈을 한정 할 수 있다.
  • 필드와 메서드에 모두 적용할 수 있다.
public class AppCtx {
	@Bean
	public MemberDao memberDao() {
		return new MemberDao();
	}

	@Bean
	@Qualifier("printer") // 자동 주입 대상 빈을 한정할 수 있다.
	//해당 빈의 한정 값으로 "printer"를 지정
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean
	public MemberPrinter memberPrinter2() {
		r
package spring;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;


public class MemberListPrinter {
	
	private MemberDao memberDao;
	private MemberPrinter memberPrinter;
	
	
	public void printAll() {
		Collection<Member> members = memberDao.selectAll();
		System.out.println(members);
		members.forEach(m->memberPrinter.print(m));
	}

	@Autowired
	public void setMemberDao(MemberDao memberDao) {
		this.memberDao = memberDao;
	}

	@Autowired
	@Qualifier("printer") // printer로 지정한 빈을 주입 받는다.
	public void setPrinter(MemberPrinter printer) {
		this.memberPrinter = printer;
	}
	
	
}

빈 이름과 기본 한정자

  • 빈 설정에 @Qualifer 애노테이션이 없으면 빈의 이름을 한정자로 지정한다
  • 같은 타입의 빈을 주입받는경우 타입일치하는게 2개이상이면 이름이 같은 빈을 주입한다.
	@Bean
	@Qualifier("printer") // 자동 주입 대상 빈을 한정할 수 있다.
	//해당 빈의 한정 값으로 "printer"를 지정
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean //빈의 이름은 memberPrinter2
	public MemberPrinter memberPrinter2() {
		return new MemberPrinter();
	}

상위/하위 타입 관계 자동 주입

  • 상속한 클래스는 상위클래스와 같은 빈으로 처리됨
  • 따라서 어떤 타입의 빈을 주입해야될지 알수없어서 오류가 발생
package spring;

public class MemberSummarayPrinter extends MemberPrinter{

	@Override
	public void print(Member member) {
		System.out.printf("회원 정보 : 이메일 =%s , 이름 = %d\n",member.getEmail(),member.getName());
	}
	
}
	@Bean
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean//MemberPrinter의 하위클래스 빈 생성
	public MemberSummarayPrinter memberPrinter2() {
		return new MemberSummarayPrinter();
	}
  • 이 문제를 해결하기위한 방법
    1. 두개의 빈의 @Qualifer를 다르게 줌
    		@Bean
      @Qualifier("printer")
    		public MemberPrinter memberPrinter1() {
    			return new MemberPrinter();
    		}
    	
    		@Bean//MemberPrinter의 하위클래스 빈 생성
      @Qualifier("summaryPrinter")
    		public MemberSummarayPrinter memberPrinter2() {
    			return new MemberSummarayPrinter();
    		}
    1. 주입하는 곳에서 타입이 하위클래스가 되도록 설정
    		@Autowired.
    		public void setPrinter(MemberSummaryPrinter printer) {
    			this.memberPrinter = printer;
    		}
profile
초보 개발자의 성장기💻

0개의 댓글