@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는 이름에 따른 의존 주입이 차이가 있다는 것을 생각하자.
'Spring 스프링 ' 카테고리의 다른 글
[스프링/Spring] MockMvc 테스트 (1) | 2018.11.27 |
---|---|
[스프링/Spring] JUnit Test (0) | 2018.11.23 |
[스프링/Spring] 생성자 방식과 설정 메서드 방식을 이용한 DI 선언하기 (0) | 2018.10.19 |
[스프링/Spring] DI를 알기 전에 GenericXmlApplicationContext 대해서 (1) | 2018.10.16 |
[스프링/Spring] DI를 왜 사용해야 할까 ? (1) | 2018.10.15 |