본문으로 바로가기
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.



@Autowired에 대해서


스프링에서는 의존을 자동으로 주입할 수 있다. 자동 주입을 사용하면 <constructor-arg/> <property/>를 사용하지 않고도 스프링이 알아서 의존 빈 객체를 찾아서 주입해 줄 수 있다.


1
2
3
4
5
6
<bean id="helloformat" class="ktko.HelloFormat">
    <property name="format" value="Hello %s!!"></property>
</bean>
 
<bean id="greeter" class="ktko.Greeter"/>
<bean id="hello" class="ktko.Hello"/>



<constructor> 태그 없이 생성자에 @Autowired를 통한 의존 주입


1
2
3
4
5
6
7
8
9
10
11
12
public class Greeter {
    private HelloFormat helloFormat;
    
    @Autowired
    Greeter(HelloFormat helloFormat) {
        this.helloFormat = helloFormat;
    }
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}



<property> 태그 없이 setter에 @Autowired를 통한 의존 주입


1
2
3
4
5
6
7
8
9
10
11
12
13
public class Hello {
    
private HelloFormat helloFormat;
    
    @Autowired
    public void setHelloFormat(HelloFormat helloFormat) {
        this.helloFormat = helloFormat;
    }
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}



필드에 @Autowired를 통한 의존 주입


1
2
3
4
5
6
7
8
public class Greeter {
    @Autowired
    private HelloFormat helloFormat;
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}



자동 주입 기능을 사용하는 것은 매우 간단하다. 아래 두 가지만 사용하면 된다.


1. 자동 주입 대상에 @Autowired 어노테이션 사용

2. XML 설정에 <context:annotation-config /> 설정 추가


위 두가지를 하면, @Autowired가 적용된 의존 주입 대상에 대해서는 <constructor-arg/> <property/> 태그를 사용할 필요 없이 의존 객체를 스프링이 알아서 주입해준다.

@Autowired 어노테이션을 사용하면 스프링은 타입을 이용해서 의존 대상 객체를 검색한다. 위의 Greeter과 Hello 클래스를 보면 의존 주입이 될 필드의 타입은 둘 다 HelloFormat이며, 따라서 이 두 의존 주입 대상에는 타입이 HelloFormat인 "helloFormat" 빈 객체가 선택된다. 


만약 같은 타입의 bean이 2개일 경우에 어떤 문제가 발생할까 ? 아래와 같이 두개의 같은 HelloFormat의 bean이 있다면 과연 어떤 bean을 선택할까 ? 


1
2
3
4
5
6
7
<bean id="helloformat" class="ktko.HelloFormat">
    <property name="format" value="Hello %s!!"></property>
</bean>
 
<bean id="helloformat2" class="ktko.HelloFormat">
    <property name="format" value="Hi %s!!"></property>
</bean>



그 결과는 둘 다 실행되지 않고 에러를 뿜어낸다. Helloformat 타입의 빈을 주입해야 하는데 helloformat빈과 helloformat2빈이 존재하여 주입할 때 선택할 수 없기 때문이다. 스프링은 이런 문제를 해결하기 위해 @Qualifier 어노테이션을 제공한다.


1
2
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'greeter' defined in class path resource [applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [ktko.HelloFormat]: : No qualifying bean of type [ktko.HelloFormat] is defined: expected single matching bean but found 2: helloformat,helloformat2; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [ktko.HelloFormat] is defined: expected single matching bean but found 2: helloformat,helloformat2
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [ktko.HelloFormat] is defined: expected single matching bean but found 2: helloformat,helloformat2



@Autowired 어노테이션이 적용된 대상에 꼭 의존 객체를 주입하지 않아도 될 때가 있다. 이런 경우에는 @required 속성의 값을 false로 지정하면 된다.


@Qualifier에 대해서 


@Qualifier 어노테이션은 사용할 의존 객체를 선택할 수 있도록 해준다. @Qualifier를 사용하려면 다음의 두 가지를 설정해주면 된다.


1. 설정에서 빈의 한정자 값을 설정한다.

2. @Autowired 어노테이션이 적용된 주입 대상에 @Qualifier 어노테이션을 설정한다. 이 때 @qualifier의 값으로 앞서 설정한 한정자를 사용한다.


한정자를 이용해서 위의 에러가 발생하는 것을 없애려면 아래와 같이 하면 된다. <bean> 태그 안에 <qualifier>태그를 이용하여 value값을 넣어 준다.


1
2
3
4
5
6
7
8
9
<bean id="helloformat" class="ktko.HelloFormat">
    <qualifier value="helloformat"/>
    <property name="format" value="Hello %s!!"></property>
</bean>
 
<bean id="helloformat2" class="ktko.HelloFormat">
    <qualifier value="helloformat2"/>
    <property name="format" value="Hi %s!!"></property>
</bean>



필드 또는 setter에 @Qualifier 어노테이션을 이용해 의존을 주입하였다. 생성자에 @Qualifier을 사용할 순 없다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Greeter {
    @Autowired
    @Qualifier("helloformat2")
    private HelloFormat helloFormat;
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}
 
public class Hello {
    private HelloFormat helloFormat;
    
    @Autowired
    @Qualifier("helloformat")
    public void setHelloFormat(HelloFormat helloFormat) {
        this.helloFormat = helloFormat;
    }
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}



@Resource에 대해서


@Autowired 어노테이션이 타입을 이용해서 주입할 객체를 검색했다면, @Resource  어노테이션은 빈의 이름을 이용해서 주입할 객체를 검색한다. @Resource 어노테이션을 사용하려면 앞서 @Autowired 어노테이션과 마찬가지로 다음의 두 가지만 추가하면 된다.


1. 자동 주입 대상에 @Resource 어노테이션 사용

2. XML 설정에 <context:annotation-config /> 설정 추가


@Resource 어노테이션은 빈의 이름을 사용해서 주입할 빈 객체를 찾기 때문에 @Resource 어노테이션의 값으로 빈 객체의 이름을 지정한다. @Resource 어노테이션은 생성자에 적용할 수 없고 필드나 메서드에만 적용할 수 있다.


1
2
3
4
5
6
7
8
public class Greeter {
    @Resource(name="helloformat")
    private HelloFormat helloFormat;
    
    public String greet(String guest) {
        return String.format(helloFormat.format,  guest);
    }
}



1
2
3
4
5
<bean id="helloformat" class="ktko.HelloFormat">
    <property name="format" value="Hello %s!!"></property>
</bean>
 
<bean id="greeter" class="ktko.Greeter"/>



@Autowired는 자료형 타입에 대한 의존 주입

@Resource는 이름에 따른 의존 주입이 차이가 있다는 것을 생각하자.