스프링의 DI

DI(dependency Injection)

의존성 주입이란

객체지향 프로그램이 비즈니스 로직을 수행하기 위해서는 상호협력하는 객체들로 구성된다. 각 객체는 다른 객체를 이용한다.

의존성 주입은 객체 외부의 assembler(container)가 객체 사이의 의존관계를 파악하고 의존 객체를 제공해주는 것을 의미

 

Inversion of Control(IoC)

기존 프로그램은 구현 객체가 스스로 필요한 객체를 생성, 연결, 실행한다.

하지만 의존성 주입이 있다면 객체가 의존 객체를 생성하거나 찾을 필요가 없다.

이렇게 제어 흐름을 직접 하는 것이 아닌 외부에서 진행되는 것을 제어의 역전이라고 한다.

 

객체들간의 의존 관계는 XML파일이나 Java설정 클래스 annotaion등을 통해 설정한다.

 

DI의 필요성

의존하는 객체를 직접 생성할 경우 의존 클래스를 다른 클래스로 변경하려면 코드 수정이 필요하다.

여러 클래스들이 의존하는 경우 모든 파일의 수정이 필요하다.

외부에 존재하는 Assembler가 의존 객체를 생성해줄 경우 클래스는 의존 객체를 전달 받기 위한 생성자나 setter method를 정의하면 된다.

 

spring의 DI

xml기반 DI설정

생성자 방식

Bean의 생성자를 통해 의존 객체를 주입한다.

-<constructor-arg>를 사용하여 생성자의 인자 값 지정

<value>값</value>

<ref bean="bean 식별자"/>

또는

<constructor-arg value="값"/>

<contstructor-arg ref-bean="bean 식별자"/>

와 같이 표현 가능

 

가장 근접한 타입의 인자를 가진 생성자를 선택한다.

단, value를 통해 전달되는 값은 기본적으로 String이므로 type속성을 이용해 다른 타입으로 변환 가능

 

-생성자 호출 시점에 딱 1번만 호출되는 것이 보장

-불변, 필수 의존관계에 사용

-성능상 유리

-Bean객체 생성 시점에 모든 의존 객체가 주입되므로 NullPointException이 발생할 가능성이 낮다

 

"c" namespace를 이용한 설정이 가능하다.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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”>
...
<bean id="bean 이름" calss="..."
	c:변수명="값" />
...

setter method 방식

Bean class에 property에 대한 setter method가 정의 되어 있어야한다.

<property> 태그를 사용하여 값이나 의존 객체를 지정하는데

마찬가지로 <value>와 <ref-bean="">을 이용함

 

"p"namesapce를 이용한 설정이 가능하다.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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”>
...
<bean id="bean 이름" class="..."
	p:변수명="변수값" />

 

-선택, 변경 가능성이 있는 의존 관계에 사용

-setter들을 별도로 실행하므로 성능이 다소 저하되고 실행 누락시 NullPointException발생 가능성이 있음

 

Collection wiring

bean perperty가 collection타입일 경우 사용한다.

<property>의 자식으로 <list><set><map><props> elemnet를 사용할 수 있다.

collection의 원소를 정의하기 위한 element들로는

<ref> : 다른 bean이나 객체

<value> : String이나 wrapper type 객체

<bean> : 내부 anonymous bean

<list>, <set>등등 : 다른 collection 객체

<null/> : null값

와 같은 것들이 있다.

 

Map type의 경우

<bean id="band" class="...">
	<property name="someband">
        <map>
			<entry>
				<key><value>HARMONIC</value></key> 
				<ref bean="harmonica" />
			</entry>
            <entry key="GUITAR" value-ref="guitar" /> 
            <entry key="CYMBAL" value-ref="cymbal" />
        </map>
	</property> 
</bean>

<entry>속성으로 key와 value를 사용한다.

bean객체를 참조할 때는 key-ref, value-ref를 사용

 

Properties type의 경우

<bean id="band" class="...">
    <property name="someband">
        <props>
            <prop key="GUITAR">STRUM STRUM STRUM</prop>
            <prop key="CYMBAL">CRASH CRASH CRASH</prop>
            <prop key="HARMONICA">HUM HUM HUM</prop>
        </props>
    </property>
</bean>

java.util.Properties는 key와 value가 모두 String인 Map과 같음

시스템 환경 변수 등 설정정보를 저장하기 위한 용도로 사용

 

SpEL

Spring Expression Language

런타임에 평가되는 식을 이용하여 값이나 객체를 생성자의 인자로 전달한다. 산술, 관계, 논리 연산들을 지원하고 정규식을 이용한 값 매칭이 가능하며 collection처리가 가능하다.

 

-일반적인 값, bean, properties, methods

<property name="name" value="#{mini}"/> <!-- String -->
<property name="age" value="#{11}"/> <!-- int -->

<property name="album" vlaue="${maxident}"/> <!-- maxident라는 bean참조 -->
<property name="song" value="#{skz.song}"/> <!-- skz라는 bean의 song property -->
<!-- song이 private인 경우 getter method 호출 -->
<property name="song" value="#{songSelector.selectorSong()}/> <!-- ㅡmethod 호출 -->

 

-T()를 이용해 클래스 이름을 인자로 지정

<property name="randomNumber" value="#{T(java.lang.math).random()}"/>

 

-연산 기호들

+, -, *, /, %, ^

<, >, ==, <=, >=, lt, gt, eq, le, ge

and, or, not, !

 

-정규식

 

-Collection 처리

<util:list> <util:set> <util.map>

<beans … xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="... http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
    <util:list id="cities">
        <bean class="…"
        p:name="Seoul"…/>
        <bean class="…"
        p:name="Pusan" …/>
        <bean class="…"
        p:name="Jeju" …/>
        <ref bean="SaltLakeCity" />
    … 
    </util:list>
<property name="chosenCity" value="#{cities[2]}"/>
<property name="randomCity" value="#{cities[T(java.lang.Math).random() * cities.size()]}"/>

 

Java코드 기반 설정

Auto-wiring
의존성 주입을 명시적으로 설정하지 않아도 container가 bean의 타입이나 이름을 이용해 자동으로 DI를 수행
*명시적 설정은 auto-wiring보다 우선적으로 적용된다

 

자바 코드 기반

@Configuration //해당 클래스를 Spring bean설정 정보로 사용

@Bean // 이 method가 생성, 반환 하는 객체를 bean객체로 등록

아래오 같은 경우 setter method기반 의존 관계 설정

@Bean
public Singer Jain(){
	Singer singer = new Singer();
    singer.setSong("song1");
    singer.setName("Jain Lee");
	return singer;
}

AnnotationConfigApplicationContext객체의 생성자에 @Configuration이 붙은 설정 클래스를 전달

설정파일이 여러개인 경우

ApplicationContext context = 
	new AnnotationConfigApplicationContext(SpringConf1.class, SpringConf2.class);

@Autowired // @Configuration이 붙은 클래스의 bena을 자동 주입하기도함

@Import // 설정 정보 결합

@Configuration
public class SpringConfSub {
    @Bean
    public Song testSong() { 
    	return new testSong();
    } …
}

import org.springframework.context.annotation.Import;
@Configuration
@Import(SpringConfSub.class) // 위 설정 클래스의 내용을 결합
public class SpringConfMain {
    @Autowired private Song testSong;
    …
}

Spring Container생성시에는 @Import를 포함한 클래스만 지정하면됨.

 

Annotation 기반 설정

XML파일에 <context:annotation-config/> 추가 : 어노테이션 처리에 필요한 모든 BeanPostProcessor bean들을 자동 등록

@Required

-property에 대한 setter method앞에 사용

-값 또는 의존 객체가 반드시 설정되어야 함을 의미

 

@Autowired

-생성자, property, method 적용가능

-할당가능한 객체가 존재하지 않을때 예외 발생(NoSuchBeanDefinitionException)

-할당가능한 객체가 여러 개 일 때 예외 발생(NoUniqueBeanDefinitionException) / 단 id가 property명과 같을 경우 그것이 주입된다.

-required 속성 사용 가능

-Collection타입의 property에 적용시 해당 원소 타입의 모든 bean들을 모아서 하나의 collection객체를 생성해 주입함

-property나 setter에 적용할때 기본생성자가 없고 인자가 있는 생성자들이 존재한다면 exception발생

-@Autowired(required=true)인 생성자는 하나만 존재해야함

 

@Nullable

-@Autowired와 함께 사용시 할당가능한 bean이 없을 때 Null

 

@Qualifier

-자동 주입 가능한 bean이 여러개 일때 특정 bean에 한정자를 붙이기 위해 사용

-@Qualifier("정의된한정자"or"bean의 Id")

 

@Value

-property, setter 또는 일반 method parameter에 적용가능

-SpEL에 사용가능

@Value("Seoul")
private String city;
@Value("5")
private int age;

 

@Resource

-어플리케이션에서 필요한 자원을 직접 지정, 검색해서 DI실행

-name이 생략되면 property와 같은 이름을 가진 bean이 주입되나 해당 bean이 없으면 같은 타입의 객체를 선택. 이도 존재하지 않을시 exception발생

 

myoskin