4. 의존 자동 주입 #5 @Autowired 애노테이션의 필수 여부

2021. 7. 12. 16:52JAVA/Spring

본 글은 초보 웹 개발자를 위한 스프링5 프로그래밍 입문 도서의 내용을 복습하기 위해 작성된 글입니다.

5. @Autowired 애노테이션의 필수 여부

@Autowired 애노테이션의 필수 여부를 지정하는 3가지 방법이 존재한다.

 

@Autowired 애노테이션 필수여부 첫번째 방법 (requied=false)

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public void print(Member member)
	{
		... 생략
	}

	@Autowired(required = false)
	public void setDateTimeFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
}

@Autowired 애노테이션의 required 속성을 false로 지정하면 매칭되는 빈이 없어도 예외가 발생되지 않고 자동 주입을 수행하지 않는다. 위 예에서 DateTimeFormatter 타입의 빈이 존재하지 않으면 예외를 발생하지 않고 setDateTimeFormatter() 메서드를 수행하지 않는다.

 

@Autowired 애노테이션 필수여부 두번째 방법 (Optional)

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public void print(Member member)
	{
		... 생략
	}

	@Autowired
	public void setDateTimeFormatter(Optional<DateTimeFormatter> formatterOpt) {
		if(formatterOpt.isPresent())
		{
			this.dateTimeFormatter = formatterOpt.get();
		}
		else
		{
			this.dateTimeFormatter = null;
		}
	}
}

자동 주입 대상 타입이 Optional인 경우, 일치하는 빈이 존재하지 않으면 값이 없는 Optional을 인자로 전달하고(예외가 발생하지 않음), 일치하는 빈이 존재하면 해당 빈을 값으로 갖는 Optional을 인자로 전달한다. Optional을 사용하는 코드는 값 존재 여부에 따라 알맞게 의존 객체를 사용하면 된다. 위 코드는 Optional#isPresent() 메서드가 true이면 값이 존재하므로 해당 값을 dateTimeFormatter 필드에 할당한다.

 

@Autowired 애노테이션 필수여부 세번째 방법 (@Nullable)

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public void print(Member member)
	{
		... 생략
	}

	@Autowired
	public void setDateTimeFormatter(@Nullable DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
}

@Autowired 애노테이션을 붙인 세터 메서드에서 @Nullable 애노테이션을 의존 주입 대상 파라미터에 붙이면, 스프링 컨테이너는 세터 메서드를 호출할 때 자동 주입할 빈이 존재하면 해당 빈을 인자로 전달하고, 존재하지 않으면 인자로 null을 전달한다.

 

@Autowired 애노테이션의 required=false 속성과 @Nullable 애노테이션의 차이점

  • required=false 속성 : 대상 빈이 존재하지 않을 시 세터 메서드 미호출
  • @Nullable 애노테이션 : 대상 빈이 존재하지 않아도 세터 메서드 호출

@Autowired 애노테이션 필수여부 방법을 필드멤버에 지정하는 방법

1. required=false 속성

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

2. Optional

public class MemberPrinter {
	@Autowired
	private Optional<DateTimeFormatter> formatterOpt;
	
	public void print(Member member)
	{
		DateTimeFormatter dateTimeFormatter = formatterOpt.orElse(null);
        if(dateTimeFormatter==null){
        ... 생략
        }
	}
}

3. @Nullable 애노테이션

public class MemberPrinter {
	@Autowired
	@Nullable
	private DateTimeFormatter dateTimeFormatter;
	
	public void print(Member member)
	{
		...
	}
}

 

5.1 생성자 초기화와 필수 여부 지정 방식 동작 이해

자동 주입 대상 필드를 기본 생성자에서 초기화한 예

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	public MemberPrinter()
	{
		dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일");
	}
	
	public void print(Member member)
	{
		if(dateTimeFormatter==null)
		{
			System.out.printf("회원 정보 : 아이디=%d, 이메일=%s, 이름=%s, 등록일=%tF\n",
					member.getId(), member.getEmail(), member.getName(), member.getRegisterDateTime());
		}
		else
		{
			System.out.printf("회원 정보 : 아이디=%d, 이메일=%s, 이름=%s, 등록일=%s\n",
					member.getId(), member.getEmail(), member.getName(),dateTimeFormatter.format(member.getRegisterDateTime()));
		}

	}

	@Autowired(required = false)
	public void setDateTimeFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}	
}

위의 코드를 실행하여 DateTimeFormatter 타입의 빈이 존재하지 않은 상태에서 MainForSpring을 실행한 뒤 info 명령어로 회원 정보를 출력해본다.

 

실행결과

@Autowired 애노테이션의 required 속성이 false이면, 매칭되는 빈이 존재하지 않을 때 기본 생성자에서 초기화한 값을 null로 바꾸지 않는다.

 

위와 같이 기본 생성자에서 초기화한 DateTimeFormatter를 사용해서 회원의 가입 일자를 출력하는 것을 확인할 수 있다.

 

위 실행결과를 통해 @Autowired 애노테이션의 required 속성이 false이면 일치하는 빈이 존재하지 않을 때 자동 주입 대상이 되는 필드나 메서드에 null을 전달하지 않는다는 것을 알 수 있다.

 

@Nullable을 적용하여 실행한 결과

@Nullable 애노테이션을 사용하면 매칭되는 빈이 존재하지 않을때 null값으로 할당, 위 실행결과에서 dateTimeFormatter 필드멤버가 null로 할당되었음으로 "yyyy년 MM월 dd일"형식으로 출력되지 않는 것을 볼 수 있다.

 

따라서 @Nullable 애노테이션을 사용할 경우 스프링 컨테이너는 의존 주입 대상이 존재하지 않으면 null을 값으로 전달한다. 스프링 컨테이너는 빈을 초기화하기 위해 기본 생성자를 이용해서 객체를 생성하고 의존 자동 주입을 처리하기 위해 setDateFormatter() 메서드를 호출한다. 그래서 기본 생성자에서 dateTimeFormatter 필드를 초기화해도 setDateFormatter() 메서드가 null을 전달받게 되어 dateTimeFormatter 필드가 다시 null로 바뀐 것이다.

 

@Autowired(required=false) 속성과 @Nullable 애노테이션, Optional의 차이

  • @Autowired(required=false) : 일치하는 빈이 없으면 setter 메서드를 수행하지 않음
  • @Nullable : 일치하는 빈이 없으면 setter 메서드를 그래도 수행하고 null을 할당한다.
  • Optional : 일치하는 빈이 없으면 값이 없는 Optional을 할당한다.

References

초보 웹 개발자를 위한 스프링5 프로그래밍 입문, 최범균 저
https://github.com/yonghwankim-dev/spring5/tree/master/sp5-chap04/src/main/java/chap04_05