리셋 되지 말자

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

Java(폐지)/spring 책

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

kyeongjun-dev 2020. 8. 12. 14:30

의사 코드(이전과 동일)

운전자가 종합 쇼핑몰에서 자동차 구매를 요청한다.
종합 쇼핑몰은 자동차를 생산한다.
종합 쇼핑몰은 타이어를 생산한다.
종합 쇼핑몰은 자동차에 타이어를 장착한다.
종합 쇼핑몰은 운전자에게 자동차를 전달한다.

Car 클래스와 tire 속성

Car라고 하는 클래스에 tire라고 하는 속성을 만들고 설정자 메서드를 만든다고 하면 보통 아래와 같은 코드가 나온다.

TIre tire;

public void setTire(Tire tire){
    this.tire=tire;
}

@Autowired를 이용한 스프링의 속성 주입 방법

expert004 패키지 생성 후 Spring Bean Configure File 생성한 뒤 우클릭 -> Open With -> Spring Config Editor 선택

하단의 Namespaces 선택

체크 메뉴 중, context에 체크한 뒤 다시 Source 탭으로 돌아옴

  • 전expert004.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


</beans>
  • 후expert004.xml
<?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-4.3.xsd">


</beans>

소스 코드

<?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-4.3.xsd">

    <context:annotation-config></context:annotation-config>
    <bean id="tire" class="expert004.KoreaTire"></bean>

    <bean id="americaTire" class="expert004.AmericaTire"></bean>
    <bean id="car" class="expert004.Car"></bean>
</beans>

@Autowired의 의미는 '스프링 설정 파일을 보고 자동으로 속성의 설정자 메서드에 해당하는 역할을 하겠다'는 의미.

  • 기존의 XML 설정 파일
    <bean id="car" class="expert003.Car">
        <property name="tire" ref="americaTire"></property>
    </bean>
  • Autowired가 적용된 새로운 XML 설정 파일
    <bean id="car" class="expert004.Car"></bean>

@Autowired를 통해 car의 property를 자동으로 엮어줄 수 있으므로(자동 의존성 주입) property 태그가 사라짐.

소스 코드

  • Tire.java 변한거 없음
  • KoreaTire.java 변한거 없음
  • AmericaTire.java 변한거 없음
  • Car.java - @Autowired를 사용하도록 변경
package expert004;

import org.springframework.beans.factory.annotation.Autowired;

public class Car {
    @Autowired
    Tire tire;

    public String getTireBrand() {
        return "장착된 타이어: " + tire.getBrand();
    }
}
  • Driver.java
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());
    }
}
  • 실행 결과
INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6bc168e5: startup date [Wed Aug 12 13:08:57 KST 2020]; 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
장착된 타이어: 코리아 타이어
  • JUnit 테스트

의존성 주입

코리아 타이어 -> 아메리카 타이어로 변경

  • 아래와 같이 bean의 id만 수정해주면 됨
<?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-4.3.xsd">

    <context:annotation-config></context:annotation-config>
    <bean id="tire2" class="expert004.KoreaTire"></bean>

    <bean id="tire" class="expert004.AmericaTire"></bean>
    <bean id="car" class="expert004.Car"></bean>
</beans>
  • 실행 결과
INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6bc168e5: startup date [Wed Aug 12 14:11:53 KST 2020]; 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
장착된 타이어: 아메리카 타이어

koreaTire 삭제, americaTire id 삭제

  • .xml
<?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-4.3.xsd">

    <context:annotation-config></context:annotation-config>
    <!-- <bean class="expert004.KoreaTire"></bean> -->

    <bean class="expert004.AmericaTire"></bean>
    <bean id="car" class="expert004.Car"></bean>
</beans>
  • 실행결과
INFO : org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6bc168e5: startup date [Wed Aug 12 14:16:14 KST 2020]; 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
장착된 타이어: 아메리카 타이어

정상적으로 실행이 된다. 왜 될까

스프링의 @Autowired는 type 기준 매칭이다. 즉 같은 타입을 구현한 클래스가 여러 개 있다면 그때 bean 태그의 id로 구분해서 매칭하게 된다.

만약 koreatire bean의 주석을 해제하면 아래와 같은 에러 메시지가 출력된다.(두 개의 빈에 매칭된다는 뜻)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'expert004.Tire' available: expected single matching bean but found 2: expert004.KoreaTire#0,expert004.AmericaTire#0

 

설정 정보를 토대로 유일한 bean을 선택할 수 없다면 스프링도 포기하는 것이다. 항상 bean 태그의 id속성을 작성하는 습관들 들이자.

 

 

Comments