본문 바로가기
Programming/Spring

의존 자동 주입

by TinKerBellBass 2017. 8. 18.
728x90
반응형

참고도서

초보 웹 개발자를 위한 스프링4 프로그래밍 입문
국내도서
저자 : 최범균
출판 : 가메출판사 2015.03.02
상세보기



1. @Autowired


(1) @Autoriwed 자동 주입 설정
스프링 XML 설정파일에 <bean>으로 등록한 객체가 필요로 하는 객체나 데이터를 
자동으로 주입해 주는 어노테이션
<constructor-arg>, <property> 엘리먼트를 사용하지 않고 
직접 자바의 생성자, 필드, 메소드에 @Autowired 어노테이션을 붙여 주입한다.

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
36
37
38
39
40
41
42
<!-- Spring XML 설정 파일 -->
 
<!-- 어노테이션이 붙은 곳에 자동 주입을 처리하라고 설정 -->
<context:annotation-config/>
 
<bean id="memberDao" class="spring.MemberDao"/>
<bean id="memberPrinter" class="spring.MemberPrinter"/>
<bean id="memberRegSvc" class="spring.MemberRegisterService"/>
<bean id="memberInfoPrinter" class="spring.MemberInfoPrinter"/>
 
 
// 자바 소스
package spring;
 
// <bean id="memberRegSvc"...> 에 의해 객체 생성
public class MemberRegisterService{
    
    private MemberDao memberDao;
    
    // <bean id="memberDao"...> 에 의해 MemberDao 객체가 생성되고
    // 생성자의 매개변수에 자동 주입된다
    @Autowired
    public MemberRegisterService(MemberDao memberDao){
        this.memberDao = memberDao;
    }
}
 
// <bean id="memberInfoPrinter"...> 에 의해 객체 생성
public class MemberInfoPrinter{
 
    // <bean id="memberDao"...> 에 의해 MemberDao 객체가 생성되고
    // MemberInfoPrinter 객체의 필드에 자동 주입된다
    @Autowired
    private MemberDao memDao;
 
    // <bean id="memberPrinter"...> 에 의해 MemberPrinter 객체가 생성되고
    // setter 메소드의 매개변수에 자동 주입된다
    @Autowired
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }    
}
cs

 

스프링 XML 설정파일에 의해 스프링 컨테이너가 구동될 때, 

bean 으로 설정된 클래스의 객체(인스턴스)가 싱글톤 범위로 생성되고,

@Autowired 어노테이션이 붙은 곳에 주입할 객체를 찾아서 자동주입한다.



(2) @Autowired의 타입 매칭


스프링 컨테이너는 @Autowired 어노테이션이 붙은 곳에 주입할 빈(bean) 객체를 찾을 때,

해당 타입에 할당할 수 있는 타입의 객체를 찾아서 주입 대상으로 선택한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 스프링 XML 설정파일 -->
<!-- CacheMemberDao 객체 생성 -->
<bean id="cachedMemDao" class="spring.CachedMemberDao"/>
 
 
// 자바 소스
package spring;
 
class MemberDao{}
// MemberDao 클래스를 상속, MemberDao의 역할을 할 수 있음(LSP 원칙)
class CachedMemberDao extends MemberDao{}
 
class MemberInfoPrinter{
    
    // CachedMemberDao는 MemberDao의 역할을 할 수 있으므로
    // 스프링 컨테이너는 CachedMemberDao 빈 객체를 자동 주입한다.
    @Autowired
    private MemberDao memDao;
}
cs


(3) <context:annotation-config/>

<context:annotation-config/> 설정을 하면 스프링 컨테이너는 아래 표의 클래스를 빈 객체로 등록한다

 AutowiredAnnotationBeanPostProcessor 

 @Autowired 에대한 의존 주입 처리

 RequiredAnnotationBeanPostProcessor

 @Required에 대한 의존 주입 처리

 ConfigurationClassPostProcessor

 @Configuration에 대한 설정 처리

 CommonAnnotationBeanPostProcessor

 JSR-250(@PostConstruct 등)에 대한 라이프사이클 처리


(4) @Autowired 의 필수 여부 지정


@Autowired 로 자동 주입하기 위해서는 반드시 스프링 XML 설정파일에 의해 의존 객체가 생성되어 있어야 한다.

만약 설정 파일에 자동 주입할 의존 객체가 존재하지 않으면 에러가 발생한다.

자동 주입할 의존 객체가 없을 때 발생하는 에러를 발생시키지 않기 위해

@Autowired 의 속성 값으로 required 를 사용한다. 


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
package spring;
 
public class MemberRegisterService{
 
    private MemberDao memberDao;
 
    // 기본 생성자가 없으면 MemberRegisterService 객체가 생성될 때
    // 무조건 MemberRegisterService(MemberDao memberDao) 생성자가 실행될 것이고
    // 이 생성자는 MemberDao 객체를 주입 받아서 생성되어야 한다.
    // 그러나 MemberDao 객체가 없으므로 MemberDao 객체를 찾을 수 없다는 에러가 발생한다
    // 그래서 기본 생성자 반드시 필요!!
    public MemberRegisterService(){
    }
 
    // 자동주입할 객체가 없어도 에러를 발생시키지 않는다.
    // 만약 자동주입할 객체가 있으면 자동 주입한다.
    @Autowired(required=false)
    public MemberRegisterService(MemberDao memberDao){
        this.memberDao = memberDao;
    }
}
 
public class MemberInfoPrinter{
 
    @Autowired(required=false)
    private MemberDao memDao;    
}
cs


(5) @Autowired 에 자동 주입할 수 있는 타입의 빈 객체가 두 개 이상일 때


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
36
37
38
39
40
<!-- Spring XML 설정 파일 -->
<bean id="printer1" class="spring.MemberPrinter"/>
<bean id="printer2" class="spring.MemberPrinter"/>
<bean id="memberInfoPrinter" class="spring.MemberInfoPrinter"/>
 
// 자바 소스
package spring;
 
class MemberInfoPrinter{
 
    MemberPrinter printer;
        
    // MemberPrinter 타입의 빈 객체가 두 개 생성되어 있으므로
    // 어느 객체를 주입해야 할지 선택할 수 없다 -> 에러 발생
    @Autowired
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }
}
 
 
<!-- id 이름과 매칭되는 메소드가 있다면 그 메소드에 자동 주입한다 -->
<!-- ex) id="printer" / setPrinter(){} -->
<!-- id 속성 값의 첫 글자를 대문자로 바꾸고 앞에 set을 붙인 메소드명 -->
<!-- Spring XML 설정 파일 -->
<bean id="printer" class="spring.MemberPrinter"/>
<bean id="printer2" class="spring.MemberPrinter"/>
 
 
// 자바 소스
package spring;

class MemberInfoPrinter{
    MemberPrinter printer;
        
    // MemberPrinter 타입의 빈 객체가 두 개 생성되어 있으나
    //  setPrinter(){} -> id="printer" 를 찾아서 자동 주입한다
    @Autowired
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }
}
cs


(6) @Autowired 어노테이션 적용 순서


① 타입이 같은 빈 객체를 검색, 검색된 객체가 한 개면 그 빈 객체를 사용

(@Qualifier 가 명시되어 있을 경우, qulifier 의 한정자와 같은 값을 같는 객체여야 함)

② 타입이 같은 빈 객체가 두 개 이상 존재하면, @Quilifier 로 지정한 빈 객체를 찾음. 존재하면 사용

③ 타입이 같은 빈 객체가 두 개 이상 존재하고 @Quilifier 가 없을 경우, 이름이 같은 빈 객체를 찾음

    존재하면 그 객체를 사용

④ ①②③에 해당하는 객체가 없으면 에러 발생


(7) @Autowired 어노테이션과 파라미터 개수


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 파라미터가 두 개 이상인 메소드나 생성자에 @Autowired 적용
 
public class MemberInforPrinter{
    
    private MemberDao memDao;
    private MemberPrinter printer;
 
    // 빈 객체만 생성되어 있다면 매개변수 수에 상관 없이 자동 주입된다
    // 여러 매개변수 중 특정 매개변수에만 주입할 객체 지정(Qualifier)
    // injectDependency(MemberDao memberDao, @Qualifier("sysout")MemberPrinter printer)
    @Autowired
    public void injectDependency(MemberDao memberDao, MemberPrinter printer){
        this.memberDao = memberDao;
        this.printer = printer;
    }
}
cs



2. @Qualifier

자동 주입 가능한 동일한 타입의 빈 객체가 두 개 있고, id 이름과 매칭되는 메소드가 없으면 
@Autowired 어노테이션은 어느 객체를 주입해야 할지 선택할 수 없기 때문에 에러가 발생한다.
이 때 @Qualifier 어노테이션을 사용하여 주입할 의존 객체를 선택할 수 있다.

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
<!-- Spring XML 설정 파일 -->
 
<bean id="printer1" class="spring.MemberPrinter">
    <!-- 한정자(qualifier) 값을 설정
    <qualifier value="sysout"/>
</bean>
 
<bean id="printer2" class="spring.MemberPrinter"/>
<bean id="memberInfoPrinter" class="spring.MemberInfoPrinter"/> 
 
// 자바 소스
package spring;
 
public class MemberInfoPrinter{
 
    MemberPrinter printer;
 
    // @Qualifier 어노테이션을 붙이고 XML에서 설정한 한정자 값을 사용
    // id="printer1" 의 빈 객체가 자동 
    @Autowired
    @Qualifier("sysout")
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }
}
cs


3. @Resource

(1) @Resource 자동 주입 설정

@Autowired 어노테이션이 타입을 이용해서 주입할 객체를 검색한다면,
@Resource 어노테이션은 빈의 이름을 이용해서 주입할 객체를 검색한다.
그리고 @Autowired 어노테이션은 생성자, 필드, 메소드 모두에 사용 가능하지만,
@Resource 어노테이션은 필드, 메소드에만 사용 가능하고, 생성자에는 사용 불가능하다.

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
36
37
38
39
<!-- Spring XML 설정 파일 -->
 
<!-- 어노테이션이 붙은 곳에 자동 주입을 처리하라고 설정 -->
<context:annotation-config/>
 
<bean id="memberDao" class="spring.MemberDao"/>
<bean id="memberPrinter" class="spring.MemberPrinter"/>
<bean id="memberRegSvc" class="spring.MemberRegisterService"/>
<bean id="memberInfoPrinter" class="spring.MemberInfoPrinter"/>
 
 
// 자바 소스
package spring;
 
// <bean id="memberRegSvc"...> 에 의해 객체 생성
public class MemberRegisterService{
    // 빈으로 설정한 id 속성 값과 @Resource 어노테이션의 name 속성 값이 같다
    // 생성된 빈 객체 중 name 속성 값과 같은 id 속성 값을 가지는 객체를 찾아서 자동 주입 
    // name="memberDao" id="memberDao"
    @Resource(name="memberDao")
    private MemberDao memberDao;   
}
 
// <bean id="infoPrinter"...> 에 의해 객체 생성
public class MemberInfoPrinter{
 
    @Resource(name="memberDao")
    private MemberDao memDao;
    private MemberPrinter printer;
 
    public void setMemberDao(MemberDao memberDao){
        this.memberDao = memberDao;
    }
  
    @Resource(name="memberPrinter")
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }    
}
cs


@Resource 어노테이션에 name 속성을 생략하면 적용된 필드나 메소드이 타입을 사용해서 빈 객체를 찾는다.

만약 해당 타입의 빈 객체가 존재하지 않거나 두 개 이상 존재할 경우 에러가 발생한다.


그리고 name 속성을 가지고 있을 때, 지정한 이름을 가지는 빈 객체가 없으면 에러가 발생한다.


(2) @Resource 어노테이션 적용 순서


① name 속성에 지정항ㄴ 빈 객체를 찾는다. 존재하면 해당 객체를 자동 주입

② name 속성이 없을 경우, 동일한 타입을 갖는 빈 객체를 찾는다. 존재하면 해당 객체를 자동 주입

③ name 속성이 없고 동일한 타입을 갖는 빈 객체가 두 개 이상일 경우, 같은 이름을 가진 빈 객체를 찾는다.

    존재하면 해당 객체를 자동 주입

④ name 속성이 없고 동일한 타입을 갖는 빈 객체가 두 개 이상이고, 같은 이름을 가진 빈 객체가 없는 경우

    @Qualifier 를 이용해서 주입할 객체를 찾는다.

⑤ ①②③④에 해당하는 객체가 없으면 에러가 발생


4. 자동 주입과 명시적 의존 주입 간의 관계

@Autowired / @Resource 를 사용한 자동 주입보다
<constructor-arg> / <property> 를 사용한 명시적 의존 주입이 우선 주입된다.
즉 명시적 의존 주입이 자동 주입보다 우선순위가 높다.

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
<!-- Spring XML 설정 파일 -->
<context:annotation-config/>
 
<bean id="memberDao" class="spring.MemberDao"/>
<bean id="memberRegSvc" class="spring.MemberRegisterService"/>
<bean id="printer" class="spring.MemberPrinter"/>
<bean id="printer2" class="spring.MemberPrinter"/>
 
<bean id="memberInfoPrinter" class="spring.MemberInfoPrinter">
    <!-- 우선 순위가 높다, MemberInfoPrinter 객체가 생성될 때, -->
    <!-- setPrinter(MemberPrinter printer) 메소드에 id 가 printer2 객체가 주입된다 --> 
    <property name="printer" ref="printer2">
</bean>
 
 
// 자바 소스
public class MemberInfoPrinter{
 
    @Autowired
    private MemberDao memDao;
    private MemberPrinter printer;
 
    public void setMemberDao(MemberDao memberDao){
        this.memberDao = memberDao;
    }
  
    // setPrinter() -> id 가 printer 인 객체를 주입
    // 하지만 명시적 주입보다 우선 순위가 낮아 printer2 가 주입된다.
    @Autowired
    public void setPrinter(MemberPrinter printer){
        this.printer = printer;
    }    
}
cs


728x90
반응형

'Programming > Spring' 카테고리의 다른 글

Bean 라이프 사이클과 범위  (0) 2017.08.19
자바 코드를 이용한 설정  (0) 2017.08.19
Spring DI  (0) 2017.08.18
Maven / Spring 기본  (0) 2017.08.18
JPA 스프링 연동  (0) 2017.08.14

댓글