여니의 프로그래밍 study/Spring & Spring Boot

[Spring] 의존 자동 주입 (Chapter 4)

여니's 2023. 8. 12. 01:41

참고 자료 : 초보 개발자를 위한 스프링5 프로그래밍 입문

해당 게시글은 초보 개발자를 위한 스프링5 프로그래밍 입문


1. @Autowired , @Resource

의존 자동 주입 기능이 있는 어노테이션

 

@Autowired

: Spring에서 지원하는 어노테이션으로

주입하려고 하는 객체의 타입이 일치하는지 찾고

객체를 자동으로 주입한다. 

타입 탐색 < 타입이 없으면 속성명이 일치하는 bean 탐색 > 일치하는 bean이 없을 경우 @Qualifier 어노테이션을 찾는다.

 

사용할 수 있는 위치는 멤버변수, setter 메소드

 

 

@Resource

: Java에서 지원하는 어노테이션이다.

name 속성의 이름을 기준으로 탐색 

> 없으면 타입 > 타입도 없으면 @Qualifier 어노테이션의 유무를 찾아서

그 어노테이션이 붙은 속성에 의존성을 주입함.

 

사용할 수 있는 위치는 멤버변수, setter 메소드, 생성자, 일반 메소드

 

 

@Qualifier이 뭘까?

> 타입이 동일한 bean 객체가 여러개 있을 경우

Spring에서 Exception을 일으킨다. 

예를 들어 @Autowired를 동일한 타입에 이미 사용했는데

또 다시 사용을 할 경우

 

 


2. @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;
	}

}

 

설정 클래스에서 더이상 set메서드를 이용하여

의존 주입을 수동으로 해주지 않아도 된다. 

 

 

만약 @Autowired 어노테이션을 설정한 필드에

알맞은 빈 객체가 주입되지 않았다면?

-> NullPointerException이 발생한다.

 

만약 @Autowired 어노테이션을 적용한 대상에

일치하는 빈이 없는 경우라면?

-> Exception 발생

 

만약 @Autowired 어노테이션을 붙인 주입 대상에 

일치하는 빈이 2개 이상이라면 ? 

-> Exception 발생

 

@Configuration
public class AppCtx {
	... 생략
    
    @Bean
    @Qualifier("printer")
    public MemberPrinter memberPrinter1(){
    	return new MemberPrinter();
    }
    
    @Bean
    public MemberPrinter memberPrinter2(){
    	return new MemberPrinter();
    }
 }
public class MemberListPrinter {
	private MemberDao memberDao;
    private MemberPrinter printer;
    
    ... 생략
    
    @Autowired
    @Qualifier("printer")
    public void setMemberPrinter(MemberPrinter printer(){
    	this.printer = printer;
    }
    
 }

 

@Qualifier 어노테이션의 값이 printer 이므로

memberPrinter1 타입의 빈을 자동 주입 대상으로 사용함

 

 

의존주입 대상은 memberPrinter1

 

 

주의할 사항은

MemberPrinter 타입의 빈을 주입받는 모든 @Autowired 어노테이션에

@Qualifier 어노테이션을 붙여줘야함

 

 


3. @Autowired 필수여부

1. Requried

> 자동 주입할 대상이 필수가 아니라면

@Autowired의 requried 속성을 false로 지정한다.

 

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
    
    public void print(Member member) {
    	.... 생략
    }
    
    
	@Autowired(required=false)
    public void setDateFormatter(DateTimeFormatter dateTimeFormatter){	
    	this.dateTimeFormatter = dateTimeFormatter;
    }
 }

 

이렇게 false로 지정하면

Exception은 발생하지 않고

자동 주입을 수행하지 않는다.

 

 

2. Optional 사용

 

스프링 5버전부터는

required 속성 대신

자바 8의 Optional을 사용해도 된다.

 

@Autowired
public void setDateFormatter(Optional<DateTimeFormatter> formatterOpt) {
	...
}

 

일치하는 빈이 존재하지 않으면

Optional을 인자로 전달 (Exception 방지)

 

일치하는 빈이 존재하면

해당 빈을 값으로 갖는 Optional을 인자로 전달

 

 

 

3. @Nullable 어노테이션

> 스프링 컨테이너가 세터 메서드를 호출할 때

자동 주입할 빈이 존재하면 인자를 전달하고

존재하지 않으면 인자를 null로 전달함

@Autowired
public void setDateFormatter(@Nullable DateTimeFormatter formatterOpt) {
	...
}

 

 

@Nullable, Optional은 

빈이 없어도 메서드가 호출된다

(required 속성과 다른 점).