의존성을 주입할 수 있는 대상은 다른 Spring 빈뿐만이 아니다

의존성을 주입할 수 있는 대상은 아래와 같다

  • 다른 Spring 빈 참조
  • 단순 값
  • 컬렉션
  • 널(null)
  • SpEL 표현식
다른 의존성 주입 대상들에 대해 사용하는 방법


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class CustomerRepositoryImpl implements CustomerRepository {
    
    private String driverClassName;
    private String url;
    private String username;
    private String password;
 
    public String getDriverClassName() {
        return driverClassName;
    }
 
    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }
 
    public String getUrl() {
        return url;
    }
 
    public void setUrl(String url) {
        this.url = url;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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">
 
    <bean id="hello" class="springHello.Hello"/>
    <bean id="customerService" class="service.CustomerServiceImpl">
        <constructor-arg ref="customerRepository"/>
    </bean>
    
    <bean id="customerRepository" class="repository.CustomerRepositoryImpl">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/order_system"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
 
cs

아래 xml 코드의 customerRepository 부분의 property 값들과 같이 스프링 빈이 아니어도 의존성 주입을 할수 있다

* 예제용으로 보여주었을 뿐 데이터 베이스를 구현하기 위한 더좋은 방법이 있으므로 이방법으로 할필요없는 없다

단일 필드 값만이 아니라 컬렉션 타입의 필드에도 값을 주입할 수 있다. 


 필드 타입

요소 

설명 

Collection/List 

<list> 

중복 허용 값 목록 

Collection/Set 

<set> 

중복되지 않는 값 목록 

Map  

<map> 

어떤 타입이든 허용되는 이름 값 컬렉션 

Properties 

<props> 

Sring 타입의 이름-값 컬렉션 

앞의 데이터베이스 연결 정보를 컬렉션 타입으로 정의할 때 가장 적당한 타입은 Properties 타입니다. 우리는 다음과 같이 Properties 타입의 컬렉션 필드를 정의할 수 있다. 

1
2
3
4
5
6
public class CustomerRepositoryImpl implements CustomerRepository {
    private Properties properties;
    
    public void setProperties(Properties properties){
        this.properties = properties;
    }
cs

1
2
3
4
5
6
7
8
9
10
    <bean id="customerRepository" class="repository.CustomerRepositoryImpl">
        <property name="properties">
            <props>
                <prop key="driverClassName">com.mysql.jdbc.Driver</prop>
                <prop key="url">jdbc:mysql://localhost:3306/order_system</prop>
                <prop key="username">root</prop>
                <prop key="password"></prop>
            </props>
        </property>
    </bean>
cs

Properties 값을 이용할 경우 위와 같이의존성 주입을 할수 있다. 

키값을 불러오는 형식으로 아래와 같이 사용가능하다. 

1
2
3
4
private String driverClassName = properties.getProperty("driverClassName");
private String url = properties.getProperty("url");
private String username = properties.getProperty("username");
private String password = properties.getProperty("password");
cs

이외에도 

Map, List 를 이용하는 방법들이 있으니 교재를 참조 (p119 - p 121)

필드에 null값을 주입해야 하는 경우에는 다음과 같이 <null/> 요소를 사용한다.

1
<property name="nullableProparty"><null/></property>
cs

또한 Spring 표현식 언어인 SpEL(Sproing Expression Language)의 #{} 표현식을 사용하여 필드값을 주입할 수 있다. 

1
2
3
<bean>
    <property name="property" value="#{5}" />
</bean>
cs

Spring 표현식을 이용할수 있는 값들에 대해서는 교제 p122 에 있는 표를 참조하면 된다. 


3.5 어노테이션 

XML 설정 최소화

XML 설정 파일을 사용할 때 순수하가 POJO로 Spring 빈을 수현할 수 있으며, 앞에서 살펴본 바와 같이 소스 코드를 변경시키지 않고도 설정을 변경시키는 것만으로도 유지 보수를 쉽게 할수 있게 한다는 이점을 갖게된다 

그러나 Java 코드와 설정이 분리되어 프로그램의 이해를 어렵게 하고 Spring 빈 클래스가 많아지면 XML 설정도 많아져서 개발자들이 어플리케이션을 개발하는데 어려움을 겪게되는것도 사실이다. 

이런 문제를 해결하기 위해 아래와 같은 두가지 해결책이 있다. 

  • 자동 와이어링
  • 어노테이션 와이어링
자동와이어링은 XML설정 파일은 그대로 사용하면 Spring  빈 설정을 최소한으로 할 수 있ㄷ도록 하는 기능 

어노테이션 와이어링은 XML 설정 파일을 아예 사용하거지 않거나또는, 가능한 사용을 억제하고 어노테이션을 사용하여 Spring 빈을 설정할 수 있도록 하는 기능을 제공 

여기서 와이어링이란 의존성 주입을 통해 Spring 빈을 연결하는 것을 말한다. 

Spring 프레임워크는 다음과 같은 4가지 자동 와이어링 방식을 제공

 방식

autowire 애트리뷰트 

설명 

 이름

 byName

필드와 같은 이름 (또는ID)를 가지는 빈과 자동 와이어링

 타입

 byType

필드와 같은 타입의 빈과 자동 와이어링 

 생성자

contructor 

생성자 매개 변수의 타입과 일치하는 빈을 자동 와이어링1 

자동탐색 

 autodetect

먼저 생성자 자동 와이어링이 수행되고 실패하면 타입 와이어링이 수행됨  

다음과 같이 Bean 클래스가 정의되어 있다고 하자 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Bean1 {}
public class Bean2  {
    private Bean1 bean1;
    public void setBean1(Bean1 bean){
        this.bean1 = bean1
    }
}
public class Bean3 {
    private Bean1 bean1;
    public Bean3(Bean1 bean1){
        this.bean1 = bean1;
    }
}
 
<bean id="bean1" class="Bean1"/>
cs

byName 이 지정되면 필드명과 같은 이름을 가지는 빈을 찾아 자동으로 와이어링 시킨다

-> 이름 와이어링

아래는 Bean2 크래스의 필드명이 bean1이므로 빈 이름이 bean1인 빈을 찾아서 필드에 의존성을 주입한다. 

1
<bean id="bean2" class="Bean2" autowire="byName"/>
cs


byType 이 지정되면 필드와 타입의을 가지는 빈을 찾아 자동으로 와이어링 시킨다

-> 타입 와이어링

아래는 Bean2 클래스의 bean1필드의 타입이 Bean1 클래스이므로 class 애트리뷰트가 Bean1인 bean1 빈을 찾아서 필드에 의존성을 주입시킨다. 

1
<bean id="bean2" class="Bean2" autowire="byType"/>
cs



1
<bean id="bean3" class="Bean3" autowire="constructor"/>
cs



어노태이션 와이어링
XML 설정을 최소하 하기 위해 Spring 프레임 워크는 빈 와이어링 즉, 의존성 주입을 지원하는 어노테이션을 제공한다. 이러한 기능을 어노테이션 와이어링이라고 한다. 어노테이션 와이어링을 사용하기 위해서즌 먼저 XML 설정 파일에 context 네임스페이스를 추가해야 한다. 다음과 같이 <beans> 태그 안에 context 네임스페이스를 추가한다. 
1
2
3
4
5
6
7
8
9
10
<?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.1.xsd">
    
<context:annotation-config/>
</beans>
cs

추가로 <context:annotation-config/>도 설정해 어노테이션 와이어링 사용할수 있게 한다. 

어노테이션을 사용한 의존성 주입에 사용할 수 있는 어노테이션은 다음과 같다. 


 어노테이션

제공자 

@Autowired 

Spring 

@Inject 

JSR-330 

@Resource 

JSR-250 

@Autowired 어노테이션은 Spring 프레임워크에서 제공하는 기본적인 어노테이션이다. 이 어노테이션은 필드 또는 생성자, setter 메서드에 적용할 수 있으며, 먼저 타입 와이어링을 시도한 후에 실패하면 이름 와이어링으로 후보 빈을 찾는다.

보통 아래와 같이 오토와이

1
2
3
4
public class CustomerServiceImpl implements CustomerService {    
    @Autowired
    private CustomerRepository repository;
}
cs

필드외에도 생성자와 setter 메서드에 @Autowired 애트리뷰트를 지정할 수도 있다. 

이제 XML 설정 파일에 의존성 주입을 하기 위한 설정을 생략해도 된다. 
만약 와이어링할 빈이 없는 경우 NoSuchBeanDefinitionException이 발생 
이떄 우리는 다음과 같은 두가지 방법을 사용할 수 있다. 

 방안

설정 

선택적 자동 와이어링 지정(null값 허용) 

@Autowired(required=false) 

 와이어링할 빈 지정(범위 한정)

@Qualifier("beanID") 


첫번째 방법은 와이어링을 반드시 해야 하는것은 아니라고 선택적 자동 와이어링을 지정하는것이다. 만약 자동 와이어링할 빈을 찾지 못한다면, 해당 필드에 저장되는 값은 null이 된다. 

1
2
3
import org.springframework.beans.factory.annotation.Autowired;
@Autowired(required=false)
private CustomerRepository repository;
cs

또 다른 방법은 와이어링할 빈을 지정하는 것. 달리말하면, 찾을 수 있도록 범위를 한정하는 것.ㅣ @Qualifier 어노테이션의 괄호 안에 와이어링할 빈 이름을 지정한다.

1
2
3
import org.springframework.beans.factory.annotation.Qualifier;
@Qualifier("customerRepository")
private CustomerRepository repository;
cs


Spring 프레임워크가 제공하는 @Autowired 어노테이션 외에도 Java의 JSR-330사양에 있는 @Inject 어노테이션을 사용할 수 있다. JSR-330 사양은 Java 언어가 제공하는 의존성 주입을 표준 어노테이션이 정의되어 있다. 이들 어노테이션을 사용하려면 클래스 경로에 표준 어노테이션을 구현한 jar 파일이 있어야 한다 . 우리는 Maven을 사용하므로 pom.xml 파일에 종종석을 추가하면 된다 .

1
2
3
4
5
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
cs


자동 빈 발견 

XML 설정을 사용하지 않용하지 않고도 오노테이션을 사용하여 Spring 빈을 설정 할수 있다. 


 어노테이션

설명 

@Component 

클래스가 Spring 빈임을 표시하는 범용 어노테이션 

@Service 

클래스가 서비스를 정의하고 있으ㅁ을 표시하는 @Componenet 

@Repository 

클래스가 데이터 레파지토리를 정의하고 있음을 표시하는 @Component 

@Controller 

 클래스가 Spring MVC 컨트롤러를 정의하고 있음을 표시하는 @Component

@Component 어노테이션은 가장 범용적인 Spring 빈 설정 어노테이션이다. 다음과 같이 Spring 빈 클래스에 지정하면 된다. 이때 디폴트 Spring 빈의 이름은 클래스명의 첫 문자를 소문자로 바꾼 이름이 된다. 아래 예의 Spring 빈은 customerRepositoryImpl 이된다 

1
2
3
@Component
public class CustomerRepositoryImpl implements CustomerRepository {
}
cs

Spring 빈의 이름을 변경하고 싶다면 괄호안에 이름을 지정하면 된다

1
2
3
@Component("customerService")
public class CustomerRepositoryImpl implements CustomerRepository {
}
cs

@Component 어노테이션 대신에 Spring 빈의 성격에 따라 @Service, @Repository, @Controller 어노테이션을 사용할 수 있다. @Service 어노테이션은 Spring 빈이 업무 로직을 구현한 서비스임을 나타낸다. 

1
2
3
@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
}
cs

@Repository  어노테이션은 Spring 빈이 데이터 액세서 기능을 제공하는 레파지토리임을 나타낸다. 

1
2
3
@Repository("customerRepository")
public class CustomerRepositoryImpl implements CustomerRepository {
}
cs

@Controller 어노테이션은 Spring MVC에서 컨트롤러임을 나타낸다. 

이렇게 어노테이션으로 정의한 Spring 빈을 자동으로 발견할 수 있도록 XML 설정 파일에 설정해야만 한다. 이때 XML 설정 파일에는 <context:annotation-config/> 대신에 자동으로 Spring 빈을 발견하기 위한 설정만 추가하면 된다 

1
<context:component-scan base-package="com.ensoa.order"/>
cs

base-package애트리뷰트에 지정된 패키지오 서브 패키지를 스캐닝 하여 Spring 빈을 찾아 인스턴스를 생성하고 IoC컨테이ㅅ너 즉, 어플리케이션 컨텍스트에 자동으로 등록된다. 편리하지만 POJO코드보다는 조금 복잡해진다. 그래도 직관적으로 이해할 수 있으므로 아주 유용한 기능이다.

** 중대형 프로젝트는 수십명의 작업자가 같이 작업을 하므로 자동 어노테이션보다는 기존 XML방식으로 의존성을 서술한 방식을 주로 이용한다. XML 방식이 전체적인 의존성 주입방식 파악에 훨씬 유용하기 때문이다

'Java > Spring Framework' 카테고리의 다른 글

스프링 프레임워크 마이그레이션 3.2.9 to 4.3.5  (0) 2016.12.22
Spring 한글설정  (0) 2015.03.19
Spring AOP  (0) 2015.01.19
스프링 학습 개발 도구 설치  (0) 2015.01.13
프레임 워크 배우기 좋은 웹사이트  (0) 2014.11.04

+ Recent posts