3-7 Spring DI 활용하기 - 이론(3)

서현우·2022년 5월 17일
0

스프링의정석

목록 보기
38/85

loC와 DI

  1. 제어의 역전 IoC(Inversion of Control)
  • 제어의 흐름을 전통적인 방식과 다르게 뒤바꾸는 것.

[전통적인 방식] 사용자 코드가 Framework 코드를 호출

Car car = new Car();
//사용자코드가 라이브러리를 호출
car.turboDrive(); //호출

//라이브러리
//변하는 코드(new TruboEngine() -> new SuperEngine())
void turboDrive(){
	engine = new TruboEngine();
	engine.start(); 
	...
}

[Ioc] Framework 코드가 사용자 코드를 호출

Car car = new Car();
car.drive(new SuperEngine());

//라이브러리가 사용자코드를 호출
//변하지 않는 코드
void drive(Engine engine) {
	engine.start(); //호출
	...
}
  1. 의존성 주입 DI(Dependency Injection)
  • 사용할 객체를 외부에서 주입받는 것.
    (IoC, DI는 디자인패턴의 전략패턴)

1) 수동 주입

Car car = new Car();
car.drive(new SuperEngine());

//라이브러리가 사용자코드를 호출
//변하지 않는 코드
//수동 주입
void drive(Engine engine) {
	engine.start(); //호출
	...
}

2) 자동 주입

Car car = new Car();
car.drive(new SuperEngine());

//자동 주입
@Autowired
void drive(Engine engine) {
	engine.start();
	...
}

6. 스프링 애너테이션 - @Autowired

인스턴스 변수(iv), setter, 참조형 매개변수를 가진 생성자, 메서드에 적용
알맞는 bean을 찾아서 넣어줌.

//@Autowired가 engine, doors에 자동 주입.
//생성자의 @Autowired는 생략 가능
//setter나 iv에 하나하나 직접 @Autowired를 붙이는 것 보다는
//생성자로 주입받도록 하는 것이 좋다.(주입받을 bean을 까먹을 수 있기 때문)
@Autowired
public Car(@Value("red") String color, @Value("100") int oil, Engine engine, Door[] doors) {
	this.color=color;
	this.oil=oil;
	this.engine=engine;
	this.doors=doors;
}

//@Autowired가 engine, doors에 자동 주입
@Autowired
public void setEngineAndDoor(Engine engine, Door[] doors) {
	this.engine=engine;
	this.doors=doors;
}

String container에서 "타입"으로 빈을 검색해서 참조 변수에 자동 주입(DI)
검색된 빈이 n개이면, 그 중에 참조변수와 "이름"이 일치하는 것을 주입.

주입 대상이 변수일 때, 검색된 빈이 1개 아니면 예외 발생.
주입 대상이 배열일 때, 검색된 빈이 n개라도 예외 발생X.

Class Car {
	//검색된 engine이 3개. engine, turboEngine, superEngine
	//참조변수와 이름이 일치하는 빈인 engine이 주입됨.
	//변수는 반드시 빈이 1개여야 함.
	@Autowired Engine engine;
	
	//배열은 빈이 n개 OK.
	@Autowired Engine[] engines;
	
	//자동주입 X(superEngine = null)
	//(required = false)면 빈이 0개도 OK. 예외발생X -> null.
	@Autowired(required = false)
	SuperEngine superEngine;
//("turboEngine")이 생략됨(첫글자 소문자를 name으로 함)
//배열 engines에 중복 주입OK.
@Component
class TurboEngine extends Engine {}

//배열 engines에 중복 주입OK.
@Component("engine")
class SuperEngine extends Engine {}

ApplicationContextTest.java

의존성 주입 실습

package com.fastcampus.ch3;

import org.springframework.beans.factory.annotation.*;
import org.springframework.context.*;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.*;
import org.springframework.stereotype.*;

import javax.inject.*;
import java.util.*;

@Component
@Scope("prototype")
class Door {}
@Component class Engine {}
@Component class TurboEngine extends Engine {}
@Component class SuperEngine extends Engine {}

@Component
class Car {
    @Value("red") String color;
    @Value("100") int oil;
//    @Autowired
      Engine engine;

//    @Autowired
      Door[] doors;

    //생성자가 여러개 일때는 @Autowired쓰는 것을 권장
    public Car() {}
//    @Autowired
    public Car(@Value("red") String color, @Value("100") int oil, Engine engine, Door[] doors) {
        this.color = color;
        this.oil = oil;
        this.engine = engine;
        this.doors = doors;
    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", oil=" + oil +
                ", engine=" + engine +
                ", doors=" + Arrays.toString(doors) +
                '}';
    }
}

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext ac = new GenericXmlApplicationContext("config.xml");
//      Car car = ac.getBean("car", Car.class); // 타입을 지정하면 형변환 안해도됨. 아래의 문장과 동일
        Car car  = (Car) ac.getBean("car"); // 이름으로 빈 검색
        System.out.println("car = " + car);

    }
}
profile
안녕하세요!!

0개의 댓글