제어public class A {
	private B b;
    
    public A() {
    	this.b = new B();
    }
 }public class A {
	private B b;
    
    // 제어 흐름을 A가 직접 하는 것이 아닌 A 외부에서 관리
    public A(B b) {
    	this.b = b;
    }
}
public class ItalianBMT {
	WhiteBread whiteBread;
    MozzarellaCheese mozzarellaCheese;
    ChiliSauce chiliSauce;
    MayonaiseSauce mayonaiseSauce;
    
    public ItalianBMT() {
    	this.whiteBread = new WhitedBread();
        this.mozzarellaCheese = new MozzarellaCheese();
        this.chiliSauce = new ChiliSauce();
        this.mayonnaiseSauce = new MayonnaiseSauce();
    }
}
public class ItalianBMT {
// 어떤 종류든 받을 수 있는 Interface 각각 구성
	Bread bread;
    Cheese cheese;
    List<Sauce> sauces;
    
    public ItalianBMT(Bread bread, Cheese cheese, List<Sauce> sauces) {
    this.bread = bread;
    this.cheese = cheese;
    this.sauces = sauces;
  }
}ItalianBMT가 가졌었지만 변경된 코드에서는 A가 갖도록 함객체지향 원칙을 잘 지키기 위해!
Hollywood Principle(할리우드 법칙)
Don't call us, we'll call you (우리에게 연락하지마쇼 알아서 불러줄테니)Hollywood Principle 이라 불리기도 함DIP와 IoC는 함께 사용하길 권장받는 관계
DIP(Dependency Inversion Principle) : 의존 역전 법칙
DIP를 활용하여 문제 해결
- 고수준 모델인 Italian BMT도 추상화(BREAD) 의존
- 저수준 모델인 (White BREAD)도 추상화(BREAD) 의존 하기에 DIP 만족
예제2 코드도 고수준 모듈인 ItalianBMT가 저수준 모듈인 재료들에 의존하지 않고 추상화 재료에 의존 => 이미 DIP 적용
public class ItalianBMT implements RecipeInjection{
	WhiteBread whiteBread;
    MozzarellaCheese mozzarellaCheese;
    ChiliSauce chiliSauce;
    MayonaiseSauce mayonaiseSauce;
    
    @Override
    public void inject(WhiteBread whiteBread, ...) {
    	this.whiteBread = whiteBread;
        this.mozzarellaCheese = mozzarellaCheese;
        this.chiliSauce = chiliSauce;
        this.mayonnaiseSauce = mayonnaiseSauce;
    }
}
interface RecipeInjection {
 	void inject(WhiteBread whiteBread, ....);
}DIP를 이용해 의존 관계를 분리시킨다.
의존성을 주입하는 방법을 알아봤지만, 각각의 속성들을 변경하고 싶을때는 어떻게 해야할까?
IoC와 DIP는 원칙 / DI는 IoC를 달성하는 디자인 패턴 중 하나
@Controller
public class MemberController {
	private final MemberService memverService;
    
    public MemberController(MemberService memberService) {
    	this.memberService = memberService;
    }
}@Controller
public class MemberController {
	@Autowired
	private MemberService memverService;
}MemberService 도 Spring Bean 이어야 함@Controller
public class MemberController {
	@Autowired 
	private MemberService memverService;
}@Controller
public class MemberController {
	private MemberService memberService;
    
    @Autowired
    public void setMemberService(MemberService memberService) {
    	this.memberService = memberService;
    }
}객체의 속성이 없는 빈 객체를 만들고 Setter로 의존성 주입
그럼 Setter 주입은 왜 존재하지?
@Controller
public class MemberController {
	private final MemberService memverService;
    
    // @Autowired , Spring 4.3 이후 생성자 1개면 생략 가능
    public MemberController(MemberService memberService) {
    	this.memberService = memberService;
    }
}객체의 최초 생성 시점에 Spring이 의존성 주입
Spring에서 공식적으로 추천하는 방법
공식 문서 상 생성자 주입과 Setter 주입은 혼용할 수 있지만 스프링은 생성자 주입을 추천함
생성자 주입 사용 시
생성자가 여러개라면?
@Autowired@Autowired가 여러 개 있을 경우 가장 많은 의존성을 주입할 수 있는 생성자 사용@Autowired가 붙은 모든 생성자가 사용 불가능한 경우 또는 어떤 생성자에도 @Autowired가 없을 경우 기본 생성자를 호출@Controller
public class PayController {
	private final PayService payService;
    
    public PayController(PayService payService) {
    	this.payService = payService;
    }
}private final PayService payService;naverPayService로 변경하면 자동으로 naverPayService Bean 주입@Controller
public class PayController {
	private final PayService payService;
    
    // 생성자 매개변수명 변경
    public PayController(PayService naverPayService) {
    	this.payService = payService;
    }
}@Component("abc") 이런식으로 이름 지정도 가능@Service
@Qualifier("mainPayService") // 구분자 지정
public class NaverPayService implements PayService {}@Controller
public class PayController {
	private final PayService payService;
    
    // 주입받을 구분자 입력
    public PayController(@Qualifier("main{ayService") PayService payService) {
    	this.payService = payService;
    }
}@Qualifier -> @Primary -> 변수명