본문

IoC & DI

반응형

# IoC & DI


- IoC(Inversion Of Control) : 제어의 역전

- DI(Dependency Injection) : 의존성 주입

- 주입 : 주입이란 말은 외부에서라는 뜻을 내포하고 있는 단어다.

자동차 내부에서 타이어를 생산하는 것이 아니라 외부에서 생산된 타이어를 자동차에 장착하는 작업이 주입이다.



# 스프링을 통한 의존성 주입 - @Autowired를 통한 속성 주입

import문 하나와 @Autowired 애노테이션을 이용하면 설정자 메서드를 이용하지 않고도 스프링 프레임워크가 설정파일을 통해 설정자 메서드 대신 속성을 주입하게 된다.


(1) 설정자 메서드

1
2
3
4
5
Tire tire;
 
public void setTire(Tire tire) {
    this.tire = tire;
}
cs


(2) @Autowired 적용

1
2
3
4
import org.springframework.beans.factory.annotation.Autowired;
 
@Autowired
Tire tire;
cs



의사 코드

운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다.

종합 쇼핑몰은 자동차를 생산한다.

종합 쇼핑몰은 타이어를 생산한다.

종합 쇼핑몰은 자동차에 타이어를 장착한다.

종합 쇼핑몰은 운전자에게 자동차를 전달한다.



File -> New -> Spring Project -> Spring MVC Project 선택


Source 01) Tire.java

1
2
3
4
5
package expert004;
 
public interface Tire {
    String getBrand();
}
cs

Source 02) KoreaTire.java

1
2
3
4
5
6
7
8
package expert004;
 
public class KoreaTire implements Tire {
    @Override
    public String getBrand() {
        return "Korea Tire";
    }
}
cs

Source 03) AmericaTire.java

1
2
3
4
5
6
7
8
package expert004;
 
public class AmericaTire implements Tire {
    @Override
    public String getBrand() {
        return "America Tire";
    }
}
cs

Source 04) Car.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package expert004;
 
import org.springframework.beans.factory.annotation.Autowired;
 
public class Car {
 
    @Autowired
    Tire tire;
 
    public String getTireBrand() {
        return "Fitted Tire : " + tire.getBrand();
    }
 
}
cs

Source 05) Driver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package expert004;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Driver {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("expert004/expert004.xml");
 
        Car car = context.getBean("car", Car.class);
 
        System.out.println(car.getTireBrand());
 
    }
}
cs

Source 06) expert004.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- expert004.xml에서 마우스 오른쪽 버튼을 클릭한 후 Open With -> Spring Config Editor를 차례로 선택하자. 
     편집기가 열리면 하단의 Namespaces탭을 클릭한다. 그 중에서 context를 체크하면 아래의 기울임꼴 두 줄이 자동을 삽입된다.
     그 후에 Source 탭으로 돌아와 <context:annotation-config />를 추가하고 car에 해당하는 bean 태그를 수정한 후 저장하면 된다. -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
 
    <context:annotation-config />
 
    <bean id="tire" class="expert004.KoreaTire"></bean>                 <!--  실행 o -->
    <bean id="americaTire" class="expert004.AmericaTire"></bean>          <!--  실행 x -->
 
    <bean id="car" class="expert004.Car"></bean>
 
</beans>
cs


Result)

INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1a93a7ca: startup date [Mon Jan 25 16:48:54 KST 2016]; root of context hierarchy

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [expert004/expert004.xml]

INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring

INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@548a9f61: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,tire,americaTire,car,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy

Fitted Tire : Korea Tire


@Autowired의 의미를 이해해 보자. 이것은 스프링 설정 파일을 보고 자동으로 속서으이 설정자 메서드에 해당하는 역할을 해주겠다는 의미이다. @Autowired를 통해 car의 property를 자동으로 엮어줄 수 있으므로(자동 의존성 주입) 생략이 가능해진 것이다.



# 스프링을 통한 의존성 주입 - @Resource를 통한 속성 주입


@Autowired는 스프링의 어노테이션이다. @Resource는 자바 표준 어노테이션이다. 스프링 프레임워크를 사용하지 않는다면 @Autowired는 사용할 수 없고, 오직 @Resource만을 사용해야 한다. @Autowired와 @Resource는 기능이 동일하지만 자동차에게 타이어는 재료 또는 자원, 부품이라고 할 수 있기 때문에 @Autowired 보다는 @Resource가 더욱 직관적이다. @Autowired를 @Resource으로 변경하는 것 외의 소스코드와 실행결과는 같다.


@Autowired와 @Resource 비교


 @Autowired

 @Resource 

 출처 

 스프링 프레임워크 

 표준 자바 

 소속 패키지

 org.springframework.beans.factory

 .annotaion.Autowired  

 javax.annotation.Resource

 빈 검색 방식

 byType 먼저, 못 찾으면 byName 

 byName 먼저, 못 찾으면 byType

 특이사항

 @Qualifier("") 협업 

 name 어트리뷰트

 byName 강제하기

 @Autowired

 @Qualifier("tire1") 

 @Resource(name="tire1") 


스프링이 제공하는 @Autowired와 자바가 제공하는 @Resource 중에서 손 들라고하면 @Resource룰 지지하겠다. 자동으로 주입된다는 의미에서는 @Autowired가 명확해 보이지만 실제 Car 입장에서 보면 @Resource라는 표현이 더 어울린다. 그리고 나중에 스프링이 아닌 다른 프레임워크로 교체되는 경우를 대비하면 자바 표준인 @Resource를 쓰는 것이 유리하다.


그럼 여기서 또 하나의 고민이 생기는데 @Resource는 사실 <bean> 태그의 자식 태그인 <property>태그로 해결될 수 있다. 

개발 생산성은 @Resource가 더 좋지만, <property>는 .XML파일만 봐도 DI관계를 손쉽게 확인할 수 있기 때문에 유지보수성이 좋다.


즉, 위의 내용을 정리하자면 아래와 같다.


@Autowired와 @Resource 중에서는 @Resource 추천

@Resource와 <property>중에서는 <property> 추천




출처 및 참고자료 : 스프링 입문을 위한 자바객체지향의 원리와 이해(김종민 저)

반응형

공유

댓글