๐Ÿ“‹ 4. ์˜์กด ์ž๋™ ์ฃผ์ž…


@Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•œ ์˜์กด ์ž๋™ ์ฃผ์ž…

  • ์ž๋™ ์ฃผ์ž… ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํ”„๋ง์ด ์•Œ์•„์„œ ์˜์กด ๊ฐ์ฒด๋ฅผ ์ฐพ์•„ ์ฃผ์ž…ํ•œ๋‹ค.
  • ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ์˜์กด์„ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์— @Autowiwred ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด ๋œ๋‹ค.
  • ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ์œผ๋ฉด ์Šคํ”„๋ง์ด ์ด๋ฅผ ์ฐพ์•„ ํ•„๋“œ์— ํ• ๋‹นํ•œ๋‹ค.

**@Autowired๋ฅผ ์ ์šฉํ•œ ๋Œ€์ƒ์— ์ผ์น˜ํ•˜๋Š” ๋นˆ์ด ์—†์œผ๋ฉด? **

ํ•ด๋‹น ํ•„๋“œ์— ๋Œ€ํ•œ ์˜์กด์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋‚ด์šฉ๊ณผ ํ•จ๊ป˜ ๋นˆ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

**๋งŒ์•ฝ ๋‘๊ฐœ ์ด์ƒ์ด๋ฉด? **

ํ•ด๋‹น ํƒ€์ž…์˜ ๋นˆ์ด ํ•œ๊ฐœ๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๋‹ค๋Š” ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.


@Qualifier๋ฅผ ์ด์šฉํ•œ ์˜์กด ๊ฐ์ฒด ์„ ํƒ

  • ์ž๋™ ์ฃผ์ž… ๊ฐ€๋Šฅํ•œ ๋นˆ์ด ๋‘ ๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ ์ž๋™ ์ฃผ์ž…์„ ํ•  ๋นˆ์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

์‚ฌ์šฉ ์œ„์น˜

@Bean ์„ ๋ถ™์ธ ๋นˆ ์„ค์ • ๋ฉ”์„œ๋“œ

@Configuration
public class ApplicationContextTestResourceQualifier {

    @Bean
  	@Qualifier("defaultFile")
    public File defaultFile() {
        File defaultFile = new File("defaultFile.txt");
        return defaultFile;
    }
}

@Autowired์—์„œ ์ž๋™ ์ฃผ์ž…ํ•  ๋นˆ์„ ํ•œ์ •ํ•  ๋•Œ ์‚ฌ์šฉ


public class MemberListPrinter {

	private MemberDao memberDao;
	private MemberPrinter printer;

	public MemberListPrinter(MemberDao memberDao, MemberPrinter printer) {
		this.memberDao = memberDao;
		this.printer = printer;
	}
	
  @Autowired
  @Qualifier("printer")
	public void setMemberPrint(MemberPrinter printer) {
		this.printer = printer;
	}
}
  • @Qualifier์˜ ์†์„ฑ์œผ๋กœ ์ฃผ์ž…ํ•  ๋นˆ์˜ ํ›„๋ณด๋ฅผ ํ•œ์ •ํ•œ๋‹ค.
  • ๋นˆ ์„ค์ •์— ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ์—†์œผ๋ฉด ๋นˆ์˜ ์ด๋ฆ„์„ ํ•œ์ •์ž๋กœ ์ง€์ •ํ•œ๋‹ค.

์ƒ์œ„/ํ•˜์œ„ ํƒ€์ž… ๊ด€๊ณ„์™€ ์ž๋™ ์ฃผ์ž…

MemberPrinter ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ MeberSummaryPrinter ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜์ž.

public class MemberSummaryPrinter extends MemberPrinter {

	@Override
	public void print(Member member) {
		System.out.printf(
				"ํšŒ์› ์ •๋ณด: ์ด๋ฉ”์ผ=%s, ์ด๋ฆ„=%s\n", 
				member.getEmail(), member.getName());
	}

}

๊ทธ๋ฆฌ๊ณ  AppCtx ์„ค์ •์—์„œ memberPrinter2() ๊ฐ€ ์˜ ๋นˆ ๊ฐ์ฒด๋ฅผ ์„ค์ •ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•œ๋‹ค.

@Configuration
public class AppCtx {
	// ...
	
	@Bean
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean
	public MemberSummaryPrinter memberPrinter2() {
		return new MemberSummaryPrinter();
	}
}

  • memberPrinter2() ์˜ ๋นˆ์„ MemberSummaryPrinter์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋„ ๋นˆ ์ค‘๋ณต ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • MemberSummaryPrinter๋Š” MemberPrinter ํƒ€์ž…์—๋„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” MemberPrinter ํƒ€์ž… ๋นˆ์„ ์ž๋™ ์ฃผ์ž…ํ•ด์•ผํ•˜๋Š” @Autowired๋ฅผ ๋งŒ๋‚˜๋ฉด `memberPrinter1(), memberPrinter2() ์ค‘ ์–ด๋–ค ๋นˆ์„ ์ฃผ์ž…ํ•ด์•ผํ•˜๋Š” ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

@Qualifier

	@Bean
	@Qualifier("printer")
	public MemberPrinter memberPrinter1() {
		return new MemberPrinter();
	}
	
	@Bean
	@Qualifier("summaryPrinter")
	public MemberSummaryPrinter memberPrinter2() {
		return new MemberSummaryPrinter();
	}

MemberListPrinter๊ฐ€ MemberSummaryPrinter๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก (Composition)

public class MemberListPrinter {

	private MemberDao memberDao;
	private MemberPrinter printer;

  // ...
	
	@Autowired
	public void setMemberPrinter(MemberSummaryPrinter printer) {
		this.printer = printer;
	}
}

@Autowired์˜ ํ•„์ˆ˜ ์—ฌ๋ถ€ ์ง€์ • ๋ฐฉ๋ฒ•

public class MemberPrinter {
	private DateTimeFormatter dateTimeFormatter;
	
	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
	public void setDateFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}

 // ...

dateTimeFormatter๊ฐ€ null์ธ์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‚ ์งœ ํ˜•์‹์„ ๋ฐ”๊ฟ” ์ถœ๋ ฅํ•œ๋‹ค.
์ฆ‰ ๋ฐ˜๋“œ์‹œ setDateFormatter()๋ฅผ ํ†ตํ•ด ์˜์กด ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
ํ•˜์ง€๋งŒ @Autowired๋Š” ํ•ด๋‹นํ•˜๋Š” ๋นˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

@Autowired(required = false)

์ด ๊ฒฝ์šฐ @Autowired(required = false) ์„ค์ •์œผ๋กœ ์ž๋™ ์ฃผ์ž… ๋Œ€์ƒ์ด ํ•„์ˆ˜๊ฐ€ ์•„๋‹˜์„ ๋ช…์‹œํ•œ๋‹ค.
์ด๋Ÿฌ๋ฉด ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†์–ด๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์ž๋™ ์ฃผ์ž…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค.

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

Optional

์Šคํ”„๋ง 5๋ถ€ํ„ฐ๋Š” required ์†์„ฑ ๋ง๊ณ , Optional์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

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

@Nullable

ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์„ ์˜์กด ์ฃผ์ž… ๋Œ€์ƒ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ถ™์ด๋ฉด ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ž๋™ ์ฃผ์ž…ํ•  ๋นˆ์ด ์กด์žฌํ•  ๊ฒฝ์šฐ ์ธ์ž๋กœ ๋ฐ›๊ณ , ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด null์„ ์ „๋‹ฌํ•œ๋‹ค.
์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค.

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

required ์†์„ฑ์„ false๋กœ ํ•  ๋•Œ์™€ ์ฐจ์ด์ ?

@Nullable ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ž๋™ ์ฃผ์ž…ํ•  ๋นˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์•„๋„ ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
@Autowired(required = false)์˜ ๊ฒฝ์šฐ ๋Œ€์ƒ ๋นˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์„ธํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.

์œ„์˜ ์„ธ๊ฐ€์ง€ ๋ฐฉ์‹์€ ๋ฉ”์„œ๋“œ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ•„๋“œ์—๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒ์„ฑ์ž ์ดˆ๊ธฐํ™”์™€ ํ•„์ˆ˜ ์—ฌ๋ถ€ ์ง€์ • ๋ฐฉ์‹ ๋™์ž‘

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 setDateFormatter(DateTimeFormatter dateTimeFormatter) {
		this.dateTimeFormatter = dateTimeFormatter;
	}
}

@Autowired(required = false)์ผ ๊ฒฝ์šฐ

  • dateTimeFormatter์— null์„ ํ• ๋‹นํ•˜์ง€ ์•Š๋Š”๋‹ค. setDateFormatter() ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

@Nullable

  • ์ผ์น˜ํ•˜๋Š” ๋นˆ์ด ์—†์„ ๋•Œ ๊ธฐ๋ณธ ์ƒ์„ฑ์ž์—์„œ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๊ณ  ์žˆ์–ด๋„, dateTimeFormatter์— null ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค.

์ž๋™ ์ฃผ์ž…๊ณผ ๋ช…์‹œ์  ์˜์กด ์ฃผ์ž… ๊ฐ„์˜ ๊ด€๊ณ„