Burninghering's Blog
article thumbnail
Published 2023. 3. 24. 00:03
스프링 IOC와 DI 패캠 챌린지

Inversion of Flow Control

Flow : if / for 즉, 실행 흐름이 바뀌는 것 

 

전통적인 방식 

다른 사람이 만든 라이브러리를 단순히 호출하는 것

잘 변하는 코드 부분(아랫 부분)

 

IOC

호출을 하긴  하긴 하지만, 

사용자가 제공한 코드(new SuperEngine)를 라이브러리에서 호출

잘 변하지 않는 코드 부분 (즉, 변하는 코드를 잘 변하지 않는 코드로 분리해냈다)

다른 사람이 만든 코드가 내 코드를 호출한다 

(문장이 실행되는 순서를 뒤집었다)

 

DI

new SuperEngine을 Engine engin에 수동 주입

(사용할 객체를 외부에서 주입하고 있는 것)

 

IOC 패턴에 DI가 적용되는 것이다.

(전략 패턴 : 내가 원하는대로 전략을 바꿀 수 있다)

 

library는 단순히 기능만 제공하지만,

framework은 기능뿐만 아니라 프로그래밍 패턴과 형식까지 제공한다.

 

인스턴스 변수

세터

생성자

메서드

에 붙일 수 있다

(객체를 주입한다)

각 매개변수에 알맞는 객체를 주입시켜준다.

 

생성자에는 @Autowired가 생략가능하다.

 

이 빈을 생성할 때 생성자를 이용해서 생성하고

생성자의 참조 매개변수의 타입에 맞는 빈을 찾아 다 넣어주는 것이다


@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이 나온다

@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

autosaveDir=/autosave
autosave=true
autosaveInterval=30

 

ApplicationContextTest.java

@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.외부파일로부터 값을 읽어온다

@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 +
                '}';
    }
}

 

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할 필요가 없어서 좋다(오른쪽 두번째 코드처럼 초기화할 필요가 없다는 뜻)


 

 

profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.