Spring๐ŸŒธ

Spring Core - DI

Jeein0313 2023. 4. 10. 11:41

๐Ÿ’กDI(Dependency Injection)

IoC๋ผ๋Š” ์›์น™์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋กœ, ์šฉ์–ด๋ฅผ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ๋ฒˆ์—ญํ•˜๋ฉด `์˜์กด์„ฑ ์ฃผ์ž…`์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์˜ ์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด 

 

์‹ค์ œ MemberService๋ผ๋Š” ๊ฐ์ฒด์—์„œ MemberRepository๋ผ๋Š” ๊ฐ์ฒด์— ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜, ์•„๋ž˜์— ๊ตฌํ˜„๋œ ์„ธ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋“ค์€ ๋ชจ๋‘ MemberRepository๊ฐ์ฒด์—์„œ ๊ตฌํ˜„ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ MemberRepository๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅธ MockRepository ๊ฐ์ฒด๋กœ ๊ต์ฒดํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”?

์‹ค์ œ๋กœ private final MemberRepository memberRepository = new MockRepository();๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ ๊นŒ์š”?

 

์ด๋ ‡๊ฒŒ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋ฉด ์•„๋ž˜์˜ ๊ตฌํ˜„ํ•œ ๋ฉ”์„œ๋“œ๋“ค๋„ ๋ชจ๋‘ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋‹ค๋งˆ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์ฐพ์•„ ์ˆ˜์ •ํ•˜๊ณ  ๋ฌธ์ œ์ ์ด ์—†๋Š”์ง€ ์‚ดํŽด๋ณด๋Š” ๊ณผ์ •์„ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ ๋“ค์€ ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ†ตํ•ด ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•œ๋ฐ์š”. 

 

 

์œ„ ๊ทธ๋ฆผ์—์„œ ์ž‘์„ฑ๋œ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›์Œ์œผ๋กœ์จ ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์ˆœ๊ฐ„ ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋ฉด MemberService ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ง์ ‘ ํ•ด๋‹น ํŒŒ์ผ์—์„œ MemberRepository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค ๊ฒฐ๊ตญ ์ง์ ‘ ์ฃผ์ž…ํ•  ๊ฐ์ฒด๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์ผ์ฐจ์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ด€๋ฆฌํ•˜๋Š” ์„ค์ • ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ๋ฅผ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

package com.codestates;

import com.codestates.coffee.CoffeeRepository;
import com.codestates.coffee.CoffeeService;
import com.codestates.member.MemberRepository;
import com.codestates.member.MemberService;

//์˜์กด์„ฑ ์„ค์ • ํŒŒ์ผ
public class DependencyConfig {
    
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
    
    public MemberRepository memberRepository(){
        return new MemberRepository();
    }
    
    public CoffeeService coffeeService(){
        return new CoffeeService(coffeeRepository());
    }
    
    public CoffeeRepository coffeeRepository(){
        return new CoffeeRepository();
    }
}

์ด๋ ‡๊ฒŒ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋‚˜๋ˆ„์–ด ์ž‘์„ฑํ•ด์ค€๋‹ค๋ฉด ๋” ์ด์ƒ ์„œ๋น„์Šค ๋‚ด๋ถ€์—์„œ ๊ฐ์ฒด ์ฃผ์ž… ๊ด€๋ จํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ , DependencyConfig.java์—์„œ ๊ตฌํ˜„ ๋ถ€๋ถ„๋งŒ ์ˆ˜์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, MemberService, CoffeeService๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ์ฃผ์ž…๋˜๋Š”์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†๊ณ  ์˜ค๋กœ์ง€ ์‹คํ–‰์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์šฐ๋ฆฌ๋Š” ์ง์ ‘ ์„ค์ • ํŒŒ์ผ์„ ํ†ตํ•ด ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ง์ ‘ ์„ค์ • ํŒŒ์ผ์„ ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ์˜์กด์„ฑ ์ฃผ์ž…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

๐Ÿ’ก์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ž€?

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ๋กœ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

 

๋ณดํ†ต AppllicatioinContext๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•˜๋ฉฐ, ApplicationContext๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html

 

ApplicationContext (Spring Framework 6.0.7 API)

Expose AutowireCapableBeanFactory functionality for this context. This is not typically used by application code, except for the purpose of initializing bean instances that live outside the application context, applying the Spring bean lifecycle (fully or

docs.spring.io

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” XML, ์• ๋„ˆํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์ž๋ฐ” ์„ค์ • ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์˜ˆ์ „์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ xml์„ ํ†ตํ•ด ๋ชจ๋‘ ์„ค์ •ํ•ด์คฌ์œผ๋‚˜ ์ด๋Ÿฌํ•œ ๋ณต์žกํ•œ ๋ถ€๋ถ„๋“ค์„ Spring Boot๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” DI๋ฅผ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์„œ๋กœ ๋‹ค๋ฅธ ๋นˆ์„ ์—ฐ๊ฒฐํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋นˆ์„ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

์™œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ• ๊นŒ?

๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด new ์ƒ์„ฑ์ž๋ฅผ ์จ์•ผ ํ–ˆ์—ˆ๋Š”๋ฐ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฌด์ˆ˜ํžˆ ๋งŽ์ด ์กด์žฌํ•˜๊ณ  ์„œ๋กœ ์ฐธ์กฐํ•˜๊ฒŒ ๋˜์–ด์žˆ์œผ๋ฉด, ๊ฐ์ฒด ๊ฐ„์˜ ์˜์กด์„ฑ์ด ๋†’์•„์ง€๊ณ (ํด๋ž˜์Šค ๊ฐ„ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ) ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฐ์ฒด์ง€ํ–ฅํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ ์ค‘ ํ•˜๋‚˜์ธ ๋‚ฎ์€ ๊ฒฐํ•ฉ๋„์™€ ๋†’์€ ์บก์ˆ ํ™”๊ฐ€ ์ง€์ผœ์ง€์ง€ ๋ชปํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐ์ฒด ๊ฐ„์˜ ์˜์กด์„ฑ์„ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ƒ์„ฑ ๊ณผ์ •

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด์˜จ Configuration Metatdata๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

// Spring Container ์ƒ์„ฑ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DependencyConfig.class);

์œ„ ์ฝ”๋“œ๋Š” ์• ๋„ˆํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์ž๋ฐ” ์„ค์ • ํด๋ž˜์Šค๋กœ Spring Container๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

XML ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“œ๋Š” 'ClassPathXmlApplicationContext'๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ApplicationContext ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•˜๊ฒŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ข…๋ฅ˜

์˜ค๋ธŒ์ ํŠธ์˜ ์ƒ์„ฑ๊ณผ ์˜ค๋ธŒ์ ํŠธ ์‚ฌ์ž‰์˜ ๋Ÿฐํƒ€์ž„ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” DI ๊ด€์ ์œผ๋กœ ๋ณผ ๋•Œ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ BeanFactory๋ผ ํ•˜๊ณ , DI๋ฅผ ์œ„ํ•œ BeanFactory์— ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์„ ApplicationContext๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

BeanFactory : ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ตœ์ƒ์œ„ ํด๋ž˜์Šค๋กœ ๋นˆ์„ ๋“ฑ๋กํ•˜๊ณ  ์ƒ์„ฑํ•˜๊ณ  ์กฐํšŒํ•˜๊ณ  ๋Œ๋ ค์ฃผ๋Š” ๋“ฑ ๋นˆ์„ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. getBean() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋นˆ์„ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, @Bean์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ์˜ ๋ช…์„ ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•ด ๋นˆ๋“ฑ๋ก์„ ํ•ฉ๋‹ˆ๋‹ค.

 

ApplicationContext : BeanFactory์˜ ๊ธฐ๋Šฅ์„ ์ƒ์†๋ฐ›์•„ ์ œ๊ณตํ•˜๋ฉฐ, ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ์€ BeanFactory๊ฐ€ ์ œ๊ณตํ•˜๊ณ  ๊ทธ ์™ธ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

ApplicationContext๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ

  • MessageSource : ๋ฉ”์‹œ์ง€ ๋‹ค๊ตญํ™”๋ฅผ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • EnvironmentCapable : ๊ฐœ๋ฐœ, ์šด์˜ ๋“ฑ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋“ฑ์œผ๋กœ ๋‚˜๋ˆ  ์ฒ˜๋ฆฌํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ๋™ ์‹œ ํ•„์š”ํ•œ ์ •๋ณด๋“ค์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค
  • ApplicationEventPublisher : ์ด๋ฒคํŠธ ๊ด€๋ จ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค
  • ResourceLoader : ํŒŒ์ผ, ํด๋ž˜์Šค ํŒจ์Šค, ์™ธ๋ถ€ ๋“ฑ ๋ฆฌ์†Œ์Šค๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒ

 

 

๐Ÿ’ก๋นˆ(Bean)

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์žฌ์‚ฌ์šฉ ์†Œํ”„ํŠธ์›จ์–ด ์ปดํฌ๋„ŒํŠธ๋กœ Spring ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ๋นˆ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋นˆ์€ ์ธ์Šคํ„ด์Šคํ™”๋œ ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

@Bean์ด ์ ํžŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ด์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

๋นˆ์€ ํด๋ž˜์Šค์˜ ๋“ฑ๋ก ์ •๋ณด, getter/setter ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•˜๋ฉฐ, ์ปจํ…Œ์ด๋„ˆ์— ์‚ฌ์šฉ๋˜๋Š” ์„ค์ • ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์„ค์ • ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ๋Š” XML ๋˜๋Š” ์ž๋ฐ” ์• ๋„ˆํ…Œ์ด์…˜, ์ž๋ฐ”์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋ฉฐ, ์ปจํ…Œ์ด๋„ˆ์˜ ๋ช…๋ น๊ณผ ์ธ์Šคํ„ด์Šคํ™”, ์„ค์ •, ์กฐ๋ฆฝํ•  ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

 

bean ์ ‘๊ทผ ๋ฐฉ๋ฒ•

AppicationContext๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ bean ์ •์˜๋ฅผ ์ฝ๊ณ  ์•ก์„ธ์Šค ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("memberRepository", memberRepository.class);

// use configured instance
List<String> userList = service.getUsernameList();

 

BeanDefinition

Bean์€ BeanDefinition(๋นˆ ์„ค์ • ๋ฉ”ํƒ€์ •๋ณด)๋กœ ์ •์˜๋˜๊ณ , BeanDefinition์— ๋”ฐ๋ผ์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

BeanDefinition์€ ์†์„ฑ์— ๋”ฐ๋ผ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ Bean์„ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ• ์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. @Bean or <bean> ๋‹น 1๊ฐœ์˜ ๋ฉ”ํƒ€์ •๋ณด๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. Spring์ด ์„ค์ • ๋ฉ”ํƒ€์ •๋ณด๋ฅผ BeanDefinition ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ปจํ…Œ์ด๋„ˆ ์„ค์ •์„ XML, Java๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

 

ํ•ต์‹ฌ ์ •๋ฆฌ๐Ÿ˜‰

์Šคํ”„๋ง IoC๋Š” ๊ฐ ๋นˆ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ์„ค์ • ๋ฉ”ํƒ€์ •๋ณด๋ฅผ ์ฝ์–ด๋“ค์ธ ๋’ค์—, ์ด๋ฅผ ์ฐธ๊ณ ํ•ด ๋นˆ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ”„๋กœํผํ‹ฐ๋‚˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์˜์กด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ฃผ์ž…ํ•ด์ฃผ๋Š” DI ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง€๊ณ , DI๋กœ ์—ฐ๊ฒฐ๋œ ์˜ค๋ธŒ์ ํŠธ๋“ค์ด ๋ชจ์—ฌ์„œ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•˜๊ณ  ๋™์ž‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ž€ POJO ํด๋ž˜์Šค์™€ ์„ค์ • ๋ฉ”ํƒ€์ •๋ณด๋ฅผ ์ด์šฉํ•ด IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ์กฐํ•ฉ์ž…๋‹ˆ๋‹ค.  

 

 

Bean Scope

๋นˆ์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„์œ„๋กœ, ํŠน์ • bean ์ •์˜์—์„œ ์ƒ์„ฑ๋œ ๊ฐœ์ฒด์— ์—ฐ๊ฒฐํ•  ๋‹ค์–‘ํ•œ ์˜์กด์„ฑ ๋ฐ ๊ตฌ์„ฑ ๊ฐ’ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŠน์ • bean ์ •์˜์—์„œ ์ƒ์„ฑ๋œ ๊ฐœ์ฒด์˜ ๋ฒ”์œ„๋„ ์ œ์–ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ํ•จ๊ป˜ ์ƒ์„ฑ๋˜์–ด์„œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์œ ์ง€๋˜๋ฉฐ, ์‹ฑ๊ธ€ํ†ค ๋นˆ์˜ ํ•˜๋‚˜์˜ ๊ณต์œ  ์ธ์Šคํ„ด์Šค๋งŒ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. (private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์™ธ๋ถ€์—์„œ ์ž„์˜๋กœ new๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์•„์•ผ ํ•จ)

ํ•ด๋‹น bean definition๊ณผ ์ผ์น˜ํ•˜๋Š” ID ๋˜๋Š” ID๋ฅผ ๊ฐ€์ง„ ๋นˆ์— ๋Œ€ํ•œ ๋ชจ๋“  ์š”์ฒญ์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ํ•ด๋‹น ํŠน์ • ๋นˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ข…๋ฃŒ ์‹œ ์†Œ๋ฉธ ๋ฉ”์„œ๋“œ๋„ ์ž๋™์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  bean์€ scope๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •๋˜์ง€ ์•Š์œผ๋ฉด ์‹ฑ๊ธ€ํ†ค์ž…๋‹ˆ๋‹ค.

 

 

Singleton ์‹ค์Šต

package com.codestates;

import com.codestates.member.MemberService;

public class SingletonTest {
    static DependencyConfig dependencyConfig = new DependencyConfig();
    static MemberService memberService1 = dependencyConfig.memberService();
    static MemberService memberService2 = dependencyConfig.memberService();

    public static void main(String[] args) {
        System.out.println("memberService1 : " + memberService1);
        System.out.println("memberService2 : " + memberService2);
    }
}

๊ฐ™์€ memberService๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋’ค์— ๋ถ™์€ ์ฃผ์†Œ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ˆ˜๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ์œ„ ๋ฐฉ์‹์€ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„์™€ ํšจ์œจ์„ฑ์ด ๋–จ์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ์ ์šฉ ์ฝ”๋“œ

package com.codestates.singleton;

public class SingletonService {
    //1.static ์˜์—ญ์— ๊ฐ์ฒด๋ฅผ 1๊ฐœ๋งŒ ์ƒ์„ฑ
    public static final SingletonService instance = new SingletonService();

    //2. ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์•„๋ž˜ public static ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ.
    public static SingletonService getInstance(){
        return instance;
    }

    //3. ์ƒ์„ฑ์ž๋ฅผ private์„ ์„ ์–ธํ•˜์—ฌ ์™ธ๋ถ€์—์„œ new ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋„๋ก ํ•จ.
    private SingletonService(){

    }
}
package com.codestates;

import com.codestates.member.MemberService;
import com.codestates.singleton.SingletonService;

public class SingletonTest {
    static SingletonService singletonService1 = SingletonService.getInstance();
    static SingletonService singletonService2 = SingletonService.getInstance();

    public static void main(String[] args) {
        System.out.println("memberService1 : " + singletonService1);
        System.out.println("memberService2 : " + singletonService2);
    }
}

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ฌธ์ œ์ 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๊ธธ๊ณ , ์˜์กด๊ด€๊ณ„์ƒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋˜, private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ๋ฌธ์ œ๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•ด๊ฒฐํ•ด์ค๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

  • private ์ƒ์„ฑ์ž๋กœ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์„ ๋ง‰๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜ ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›
  • ์ƒ์„ฑ, ๊ด€๊ณ„ ์„ค์ •, ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์ด ์ปจํ…Œ์ด๋„ˆ์—๊ฒŒ ์žˆ๊ธฐ ๋Œ€๋ฌธ์— ์ผ๋ฐ˜ ์ž๋ฐ” ํด๋ž˜์Šค๋„ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌ๋  ์ˆ˜ ์žˆ์Œ
  • public ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•˜๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Mock ์˜ค๋ธŒ์ ํŠธ๋กœ ๋Œ€์ฒดํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์ด ๊ฐ€๋Šฅ.
  • ๊ฐ์ฒด์ง€ํ–ฅ์  ์„ค๊ณ„์™€ ๋””์ž์ธ ํŒจํ„ด ์ ์šฉ ๊ฐ€๋Šฅ

์ด๋ ‡๊ฒŒ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‹ฑ๊ธ€ํ†ค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ผ๊ณ  ํ•˜๋ฉฐ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ๊ธฐ๋Šฅ ๋•๋ถ„์— ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ชจ๋“  ๋‹จ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉฐ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

package com.codestates;

import com.codestates.coffee.CoffeeRepository;
import com.codestates.coffee.CoffeeService;
import com.codestates.member.MemberRepository;
import com.codestates.member.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//์˜์กด์„ฑ ์„ค์ • ํŒŒ์ผ
@Configuration
public class DependencyConfig {
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository(){
        return new MemberRepository();
    }
    @Bean
    public CoffeeService coffeeService(){
        return new CoffeeService(coffeeRepository());
    }
    @Bean
    public CoffeeRepository coffeeRepository(){
        return new CoffeeRepository();
    }
}
package com.codestates;

import com.codestates.member.MemberService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SingletonTest {
    static AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(DependencyConfig.class);
    static MemberService memberService1 = ac.getBean("memberService", MemberService.class);
    static MemberService memberService2  = ac.getBean("memberService", MemberService.class);

    public static void main(String[] args) {
        System.out.println("memberService1 : " + memberService1);
        System.out.println("memberService2 : " + memberService2);
    }
}

 

์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹ ์‚ฌ์šฉ์‹œ ์ฃผ์˜์ 

์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹์€ ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋Š” ๋ฌด์ƒํƒœ๋กœ ์„ค๊ณ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์•ˆ๋˜๋ฉฐ, Read-only์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๋นˆ์˜ ๊ณต์œ  ๊ฐ’์„ ์„ค์ •ํ•˜๋ฉด ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ’กJava ๊ธฐ๋ฐ˜ Container ์„ค์ •

@Bean๊ณผ @Configuration

//DependencyConfig ํด๋ž˜์Šค
//์ปจํ…์ŠคํŠธ๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ๋•Œ
@Configuration
public class DependencyConfig{
	@Bean
	public MyService myService() {
		return new MyServiceImpl();
	}
}

ApplicationContext ๊ตฌํ˜„์€ ์•„๋ž˜์™€ ๊ฐ™์€ ์• ๋„ˆํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ ํด๋ž˜์Šค๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  • @Configuration ํด๋ž˜์Šค๊ฐ€ ์ž…๋ ฅ์œผ๋กœ ์ œ๊ณต๋  ๊ฒฝ์šฐ : @Configuration ํด๋ž˜์Šค ์ž์ฒด๊ฐ€ Bean ์ •์˜๋กœ ๋“ฑ๋ก๋˜๋„ ํด๋ž˜์Šค ๋‚ด์—์„œ ์„ ์–ธ๋œ ๋ชจ๋“  @Bean ๋ฉ”์„œ๋“œ๋„ Bean ์ •์˜๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.
  • @Component ํด๋ž˜์Šค์™€ JSR-330 ํด๋ž˜์Šค๊ฐ€ ์ œ๊ณต๋  ๊ฒฝ์šฐ : ๋นˆ ์ •์˜๋กœ ๋“ฑ๋ก๋˜๋ฉฐ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ•ด๋‹น ํด๋ž˜์Šค ๋‚ด์—์„œ @Autowired ๋˜๋Š” @Inject์™€ ๊ฐ™์€ DI ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

 

์ฝ”๋“œ

@Configuration ํด๋ž˜์Šค๋ฅผ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(DependencyConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

 

@Component ๋˜๋Š” JSR-330 ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ํด๋ž˜์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์„ฑ์ž์— ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉ

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

 

 

@Bean ์• ๋„ˆํ…Œ์ด์…˜ ์‚ฌ์šฉํ•˜๊ธฐ

@Bean์„ ๋ฉ”์„œ๋“œ์— ์ถ”๊ฐ€ํ•ด์„œ Bean์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Configuration
public class DependencyConfig {

    @Bean
    public TransferServiceImpl transferService() {
        return new TransferServiceImpl();
    }
}

 

Java ๊ธฐ๋ฐ˜ ์ปจํ…Œ์ด๋„ˆ ์„ค์ •

// DependencyConfig.java

package com.codestates.section2week4;

import com.codestates.section2week4.coffee.CoffeeRepository;
import com.codestates.section2week4.coffee.CoffeeService;
import com.codestates.section2week4.member.MemberRepository;
import com.codestates.section2week4.member.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DependencyConfig {
  @Bean
  public MemberService memberService() {
    return new MemberService(memberRepository());
  }
  @Bean
  public MemberRepository memberRepository() {
    return new MemberRepository();
  }
  @Bean
  public CoffeeService coffeeService() {
    return new CoffeeService(coffeeRepository());
  }
  @Bean
  public CoffeeRepository coffeeRepository() {
    return new CoffeeRepository();
  }
}

 

 

๐Ÿ’กComponent Scan

์Šคํ”„๋ง์€ ์„ค์ • ์ •๋ณด ์—†์ด ์ž๋™์œผ๋กœ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์•ž์—์„œ๋Š” ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ ์ž๋ฐ” ์ฝ”๋“œ์˜ @Bean or XML  ๋“ฑ์˜ ์„ค์ • ์ •๋ณด์— ๋“ฑ๋กํ•œ ์Šคํ”„๋ง ๋นˆ๋“ค์„ ์ง์ ‘์ž‘์„ฑ์„ ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ˆ˜์ž‘์—…์œผ๋กœ ๋“ฑ๋กํ•˜๊ฒŒ ๋˜๋ฉด ์„ค์ • ์ •๋ณด๋„ ์ปค์ง€๊ณ , ๋ˆ„๋ฝํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

@ComponentScan์€ @Component๊ฐ€ ๋ถ™์€ ๋ชจ๋“  ํด๋ž˜์Šค๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์„ค์ • ์ •๋ณด์— ๋ถ™์—ฌ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. (์˜์กด๊ด€๊ณ„๋„ ์ž๋™์œผ๋กœ ์ฃผ์ž…ํ•˜๋Š” @Autowired ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.)

package com.codestates.section2week4;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
@ComponentScan
public class AutoDependencyConfig {

}

๊ธฐ์กด์— ์ž‘์„ฑํ•˜๋˜ DependencyConfig์™€ ๋น„๊ตํ•œ๋‹ค๋ฉด @Bean์œผ๋กœ ๋“ฑ๋กํ•œ ํด๋ž˜์Šค๋ฅผ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋‹จ, ComponentScan์„ ์‚ฌ์šฉํ•˜๋ฉด @Configuration์ด ๋ถ™์€ ์ •๋ณด๋„ ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค.(Configuration ๋‚ด๋ถ€์— @Component๊ฐ€ ๋ถ™์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ)

 

 

@Component, @Autowired ์ถ”๊ฐ€

@Component๋Š” @ComponentScan์ด ๋“ฑ๋ก๋œ ๊ณณ์—์„œ @Component๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 

@Autowired๋Š” ์ƒ์„ฑ์ž ์˜์กด์„ฑ ์ฃผ์ž…์— ํ•„์š”ํ•œ ์„ค์ • ์ •๋ณด ๋Œ€์‹  ์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์„ ํ•ด์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

package com.codestates.section2week4.member;

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

@Component
public class MemberService {

  private final MemberRepository memberRepository;
  
  @Autowired
  public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }


  public void createMember(Member member) {
    memberRepository.postMember(member);
  }

  public Member getMember(Long memberId) {
    return memberRepository.getMember(memberId);
  }

  public void deleteMember(Long memberId) {
    memberRepository.deleteMember(memberId);
  }
}
package com.codestates.section2week4.coffee;

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

@Component
public class CoffeeService {

  private static CoffeeRepository coffeeRepository;

  @Autowired
  public CoffeeService(CoffeeRepository coffeeRepository) {
    this.coffeeRepository = coffeeRepository;
  }

  public void createCoffee(Coffee coffee) {
    coffeeRepository.postCoffee(coffee);
  }

  public Coffee editCoffee(Long coffeeId, String korName, int price) {
    return coffeeRepository.patchCoffee(coffeeId, korName, price);
  }

  public Coffee getCoffee(Long coffeeId) {
    return coffeeRepository.getCoffee(coffeeId);
  }
  public void deleteCoffee(Long coffeeId) {
    coffeeRepository.deleteCoffee(coffeeId);
  }
}
package com.codestates.section2week4.member;

import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class MemberRepository {

  private static Map<Long, Member> members = new HashMap<>();

  public void postMember(Member member) {
    members.put(member.getMemberId(), member);
  }

  public Member getMember(Long memberId) {
    return members.get(memberId);
  }

  public void deleteMember(Long memberId) {
    members.remove(memberId);
  }

}
package com.codestates.section2week4.coffee;

import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class CoffeeRepository {

  private static Map<Long, Coffee> drinks = new HashMap<>();

  public void postCoffee(Coffee coffee) {
    drinks.put(coffee.getCoffeeId(), coffee);
  }

  public Coffee patchCoffee(Long coffeeId, String korName, int price) {
    Coffee drink = drinks.get(coffeeId);
    drink.setKorName(korName);
    drink.setPrice(price);

    return drinks.put(coffeeId, drink);
  }

  public Coffee getCoffee(Long coffeeId) {
    return drinks.get(coffeeId);
  }

  public void deleteCoffee(Long coffeeId) {
    drinks.remove(coffeeId);
  }

}

 

์ปดํฌ๋„ŒํŠธ ์Šค์บ” ๊ธฐ๋ณธ ๋Œ€์ƒ

@Component : ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์—์„œ ์‚ฌ์šฉ๋จ.

@Controller, @RestController : ์Šคํ”„๋ง MVC ๋ฐ REST ์ „์šฉ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ๋จ.

@Service : ์Šคํ”„๋ง ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ์‚ฌ์šฉ๋จ.

@Repository : ์Šคํ”„๋ง์˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ณ„์ธต์—์„œ ์‚ฌ์šฉ๋จ.

@Configuration : ์Šคํ”„๋ง ์„ค์ • ์ •๋ณด์—์„œ ์‚ฌ์šฉ๋จ.(ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์†Œ์Šค ์ฝ”๋“œ์—๋Š” @Component๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์Œ)

 

 

๐Ÿ’ก๋‹ค์–‘ํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋ฐฉ๋ฒ•

  • ์ƒ์„ฑ์ž ์ฃผ์ž…
  • ์ˆ˜์ •์ž ์ฃผ์ž…(setter ์ฃผ์ž…)
  • ํ•„๋“œ ์ฃผ์ž…
  • ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

์ƒ์„ฑ์ž ์ฃผ์ž…

์ƒ์„ฑ์ž์— @Autowired๋ฅผ ํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— @Component๋กœ ๋“ฑ๋ก๋œ ๋นˆ์—์„œ ์ƒ์„ฑ์ž์— ํ•„์š”ํ•œ ๋นˆ๋“ค์„ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.

 

ํŠน์ง•)

  • ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ์ ์— ๋”ฑ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋จ.
  • ๋ถˆ๋ณ€๊ณผ ํ•„์ˆ˜ ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ๋จ
  • ์ƒ์„ฑ์ž๊ฐ€ 1๊ฐœ๋งŒ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” @Autowired๋ฅผ ์ƒ๋žตํ•ด๋„ ์ž๋™ ์ฃผ์ž…๋จ
  • NullPointerException์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ
  • ์ฃผ์ž…๋ฐ›์„ ํ•„๋“œ๋ฅผ final๋กœ ์„ ์–ธ ๊ฐ€๋Šฅ

์ˆ˜์ •์ž ์ฃผ์ž…(setter ์ฃผ์ž…)

setter๋ผ ๋ถˆ๋ฆฌ๋Š” ํ•„๋“œ์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์˜์กด ๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

ํŠน์ง•)

  • ์„ ํƒ๊ณผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ๋จ.
  • ์ž๋ฐ” Bean ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ์˜ ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
@Component
public class CoffeeService {
  private MemberRepository memberRepository;
  private CoffeeRepository coffeeRepository;

  @Autowired
  public void setMemberRepository(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }

  @Autowired
  public void setCoffeeRepository(CoffeeRepository coffeeRepository) {
    this.coffeeRepository = coffeeRepository;
  }
}

์ƒ์„ฑ์ž ์ฃผ์ž…๊ณผ์˜ ์ฐจ์ด์ ์€ ์ƒ์„ฑ์ž ๋Œ€์‹  set ํ•„๋“œ๋ช… ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ˆ˜์ •์ž์˜ ๊ฒฝ์šฐ @Autowired๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์œผ๋ฉด ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

์ƒ์„ฑ์ž๋Š” 1๊ฐœ์ผ๋•Œ @Autowired๊ฐ€ ์—†์–ด๋„ ์ž‘๋™์ด ๋˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡?

์Šคํ”„๋ง์ด ํ•ด๋‹น ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋นˆ์„ ๋„ฃ์–ด์•ผ ํ•˜๋Š”๋ฐ ์ƒ์„ฑํ•  ๋•Œ ์ƒ์„ฑ์ž๋ฅผ ๋ถ€๋ฅผ ์ˆ˜ ๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋นˆ์„ ๋“ฑ๋กํ•˜๋ฉด์„œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๋„ ๊ฐ™์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

ํ•„๋“œ ์ฃผ์ž…

ํ•„๋“œ์— @Autowired ๋ถ™์—ฌ์„œ ๋ฐ”๋กœ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

ํŠน์ง•)

  • ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์„œ ์˜ˆ์ „์— ๋งŽ์ด ์‚ฌ์šฉ๋œ ๋ฐฉ์‹์ด๋‚˜, ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ํž˜๋“ค๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • DI ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์—†์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์‹ค์ œ ์ฝ”๋“œ์™€ ์ƒ๊ด€์—†๋Š” ํŠน์ • ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ๊ฒฐ๊ตญ setter๊ฐ€ ํ•„์š”ํ•ด ์ˆ˜์ •์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
@Component
public class CoffeeService {
  @Autowired
  private MemberRepository memberRepository;
  @Autowired
  private CoffeeRepository coffeeRepository;
}

 

์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

๋ง๊ทธ๋Œ€๋กœ ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

ํŠน์ง•)

  • ํ•œ๋ฒˆ์— ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
package com.codestates;

import com.codestates.member.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.lang.Nullable;


import java.util.Optional;

public class AutowiredTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
    }

    static class TestBean{
        @Autowired(required=false) //์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ.
        public void setNoBean1(Member noBean1){
            System.out.println("noBean1 = "+noBean1);
        }

        @Autowired
        public void setNoBean2(@Nullable Member noBean2){//์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด null์ด ์ž…๋ ฅ๋จ.
            System.out.println("noBean2 = " + noBean2);
        }

        @Autowired
        public void setNoBean3(Optional<Member> noBean3){//Optinoal.emty๊ฐ€ ์ž…๋ ฅ๋จ.
            System.out.println("noBean3 = " + noBean3);
        }
    }
}

 

์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

  • ๋ถˆ๋ณ€
    • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์€ ์ฒ˜์Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋  ๋•Œ ๋Œ€๋ถ€๋ถ„ ์ •ํ•ด์ง€๊ณ , ์ข…๋ฃŒ ์ „๊นŒ์ง€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ณ  ๋ณ€๊ฒฝ๋˜์–ด์„œ๋Š” ์•ˆ๋จ.
    • ์ˆ˜์ •์ž ์ฃผ์ž… ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์ด๋ฆ„ ๋ฉ”์„œ๋“œ๋ฅผ public์œผ๋กœ ์—ด์–ด๋‘์–ด ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ ํ•ฉํ•˜์ง€ ์•Š์Œ.
    • ๋ˆ„๊ตฐ๊ฐ€ ์‹ค์ˆ˜๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜๋„ ์žˆ๊ณ , ์• ์ดˆ์— ๋ณ€๊ฒฝํ•˜๋ฉด ์•ˆ๋˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹˜.
    • ์ƒ์„ฑ์ž ์ฃผ์ž…์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜ ๋•Œ ์ตœ์ดˆ๋กœ 1๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๊ณ  ๊ทธ ์ดํ›„์—๋Š” ๋‹ค์‹œ๋Š” ํ˜ธ์ถœ๋˜๋Š” ์ผ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๋ณ€ํ•˜๊ฒŒ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Œ.
  • ๋ˆ„๋ฝ
    • ํ˜ธ์ถœํ–ˆ์„ ๋•Œ๋Š” NPE(Null Pointer Excpetion)์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ๋ˆ„๋ฝ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•จ.
    • ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฃผ์ž… ๋ฐ์ดํ„ฐ ๋ˆ„๋ฝ ์‹œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จ.
  • final ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    • ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.
    • ์ƒ์„ฑ์ž์—์„œ ๊ฐ’์ด ์„ค์ •๋˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ ์‹œ์ ์—์„œ ์˜ค๋ฅ˜๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์Œ.
    • java: variable (๋ฐ์ดํ„ฐ ์ด๋ฆ„) might not have been initialized
    • ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ์ฃผ์ž… ๋ฐฉ์‹์€ ์ƒ์„ฑ์ž ์ดํ›„์— ํ˜ธ์ถœ๋˜๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉ ๋ถˆ๊ฐ€
  • ์ˆœํ™˜ ์ฐธ์กฐ
    • ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Œ.
    • ๊ฐœ๋ฐœํ•˜๋‹ค๋ณด๋ฉด ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์— ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๊ฒŒ ๋จ (A→B๋ฅผ ์ฐธ์กฐํ•˜๊ณ , B→ A๋ฅผ ์ฐธ์กฐ)
    • ํ•„๋“œ ์ฃผ์ž…๊ณผ ์ˆ˜์ •์ž ์ฃผ์ž…์€ ๋นˆ์ด ์ƒ์„ฑ๋œ ํ›„์— ์ฐธ์กฐ๋ฅผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์–ด๋– ํ•œ ์˜ค๋ฅ˜์™€ ๊ฒฝ๊ณ  ์—†์ด ๊ตฌ๋™๋จ
      • ์‹ค์ œ ์ฝ”๋“œ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๊นŒ์ง€ ๋ฌธ์ œ๋ฅผ ์•Œ ์ˆ˜ ์—†์Œ.
    • ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ฃผ์ž…ํ•˜๊ฒŒ ๋˜๋ฉด BeanCurrentlyInCreationException์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋จ.