
Inversion of Flow Control
Flow : if / for 즉, 실행 흐름이 바뀌는 것
전통적인 방식
다른 사람이 만든 라이브러리를 단순히 호출하는 것
잘 변하는 코드 부분(아랫 부분)
IOC
호출을 하긴 하긴 하지만,
사용자가 제공한 코드(new SuperEngine)를 라이브러리에서 호출
잘 변하지 않는 코드 부분 (즉, 변하는 코드를 잘 변하지 않는 코드로 분리해냈다)
다른 사람이 만든 코드가 내 코드를 호출한다
(문장이 실행되는 순서를 뒤집었다)
DI
new SuperEngine을 Engine engin에 수동 주입
(사용할 객체를 외부에서 주입하고 있는 것)
IOC 패턴에 DI가 적용되는 것이다.
(전략 패턴 : 내가 원하는대로 전략을 바꿀 수 있다)
library는 단순히 기능만 제공하지만,
framework은 기능뿐만 아니라 프로그래밍 패턴과 형식까지 제공한다.

인스턴스 변수
세터
생성자
메서드
에 붙일 수 있다
(객체를 주입한다)
각 매개변수에 알맞는 객체를 주입시켜준다.
생성자에는 @Autowired가 생략가능하다.
이 빈을 생성할 때 생성자를 이용해서 생성하고
생성자의 참조 매개변수의 타입에 맞는 빈을 찾아 다 넣어주는 것이다
<java />
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
// @Autowired
Engine engine;
// @Autowired
Door[] doors;
// @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;
}
기본 생성자가 있으면,
기본 생성자를 먼저 사용하므로
engine과 door에 null이 나온다
<code />
@Component
class Car {
@Value("red") String color;
@Value("100") int oil;
// @Autowired
Engine engine;
// @Autowired
Door[] doors;
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;
}

이럴땐 기본 생성자와 생성자중 어떤 생성자를 사용해서 객체를 주입시킬건지
@Autowired를 붙여준다

참조변수에 객체 주소를 저장해준다 = 객체를 주입해준다
만약 여러 개라면, 타입이 아니라 이름이 일치하는 것을 주입한다
주입 대상이 변수일 때와 배열일 때가 다르다
변수일 때는 1개가 아니면 예외 발생
배열일 때는 여러개라도 예외 발생 X -> 배열에 다 담으면 되니까!

@Resource(name="engine")에서 이름 생략 가능
@Autowired를 쓰고 같은 타입의 빈이 여러 개 있으면 @Qualifier로 어떤 것을 주입해줄지 지정해줄 수 있다.
이렇게 두 개의 방식이 있다.

컴포넌트 스캔을 할 때, 베이스 패키지의 서브 패키지까지 다 뒤진다.
컴포넌트가 붙은 것을 다 찾아서 빈으로 등록한다.
주석 처리된, 위아래 문장 xml과 @Component가 같은 문장이다.
매타 애노테이션 = 애노테이션을 만들 때 쓰는 애노테이션
컴포넌트가 붙은 것은 컴포넌트 스캔 태그에 의해 자동으로 빈으로 등록된다!

@Value 어노테이션은 값을 지정해주는 어노테이션인데,
특별한 기능이 있다
시스템 프로퍼티 값이나 시스템 인바이런먼트 값을 읽어올 수 있다
PWD => 현재 작업 디렉토리
user.timezone => 사용자의 시간대
또한 파일로부터 값을 읽어올 수 있다
=를 구분자로 해서 값을 읽어온다
setting.properties
<code />
autosaveDir=/autosave
autosave=true
autosaveInterval=30
ApplicationContextTest.java
<code />
@Component
@PropertySource("setting.properties")
class SysInfo{
String timeZone;
String currDir;
String autosaveDir;
int autosaveInterval;
boolean autosave;
@Override
public String toString() {
return "SysInfo{" +
"timeZone='" + timeZone + '\'' +
", currDir='" + currDir + '\'' +
", autosaveDir='" + autosaveDir + '\'' +
", autosaveInterval=" + autosaveInterval +
", autosave=" + autosave +
'}';
}
}
@Value를 사용해서
1.시스템 프로퍼티 값이나 시스템 인바이런먼트 값을 읽어올 수 있다
2.외부파일로부터 값을 읽어온다
<code />
@Component
@PropertySource("setting.properties")
class SysInfo{
@Value("#{systemProperties['user.timezone']}")
String timeZone;
@Value("#{systemEnvironment['APPDATA']}")
String currDir;
@Value("${autosaveDir}")
String autosaveDir;
@Value("${autosaveInterval}")
int autosaveInterval;
@Value("${autosave}")
boolean autosave;
@Override
public String toString() {
return "SysInfo{" +
"timeZone='" + timeZone + '\'' +
", currDir='" + currDir + '\'' +
", autosaveDir='" + autosaveDir + '\'' +
", autosaveInterval=" + autosaveInterval +
", autosave=" + autosave +
'}';
}
}

<code />
Map<String,String> map = System.getenv();
System.out.println("map = " + map);
Properties properties = System.getProperties();
System.out.println("properties = " + properties);

종류가 굉장히 많다...

JSR = Java Spec Request
스프링 애너테이션은 스프링에서 제공
표준 애너테이션은 자바에서 제공
스프링 애너테이션을 쓰는게 낫지만,
@Resource를 쓰려면 annotations-api.jar가 필요하다

property 태그를 이용해 빈을 초기화할 수 있다. setter가 있어야만 사용할 수 있다
property 태그를 사용하면 설정파일에 다 들어있으니까 set할 필요가 없어서 좋다(오른쪽 두번째 코드처럼 초기화할 필요가 없다는 뜻)


'패캠 챌린지' 카테고리의 다른 글
스프링으로 DB 다루기 (0) | 2023.03.29 |
---|---|
Spring으로 DB 연결하기 (0) | 2023.03.28 |
스프링 DI 활용하기 - 이론 (0) | 2023.03.23 |
스프링 DI 활용하기 - 실습 (0) | 2023.03.22 |
스프링 DI 흉내내기 - 객체 찾는 법 (by type/by name) (0) | 2023.03.22 |