Web/Spring 2018. 3. 13. 16:07

스프링에서 어노테이션을 이용한 DI 방법



1.@Autowired,@Resource,@Qualfier 어노테이션


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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.web.nuri;
 
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
 
import javax.annotation.Resource;
 
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
 
import com.web.nuri.user.UserDTO;
import com.web.nuri.user.UserService;
 
//JUnit 확장기능들(import문은 수동으로 넣어줘야한다)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/test-applicationContext.xml"//테스트용 applicationContext.xml kodictest/kodictest
public class UserDAOTest {
    @Resource(name="userServiceImpl")
    UserService userService;
    @Autowired
    PlatformTransactionManager transactionManager;
    
    //트랜잭션 경계설정 코드
    @Test(expected=DataAccessException.class)
    public void insertUserTest() {
        //트랜잭션의 시작을 알린다.(트랜잭션을 얻어오는 시점이 시작)
        TransactionStatus status=this.transactionManager.getTransaction(new DefaultTransactionDefinition());
        UserDTO user1=new UserDTO();
        UserDTO user2=new UserDTO();
        UserDTO user3=new UserDTO();
        try {
            user1.setId("test@test.com");
            user1.setPw("1111");
            user1.setNickName("tester");
            user2.setId("test1@test.com");
            user2.setPw("1111");
            user2.setNickName("tester1");
            user3.setId("test@test.com");
            user3.setPw("1111");
            user3.setNickName("tester2");
        
            userService.insertUser(user1);
            userService.insertUser(user2);
            userService.insertUser(user3);
            this.transactionManager.commit(status);
        }catch (RuntimeException e) {
            // TODO: handle exception
            this.transactionManager.rollback(status);
            throw e;
        }
        //UserDTO user4=userService.getUser(user1);
        //assertThat(user2.getId(),is(user1.getId()));
        //userService.deleteUser(user);
    }
}
 
cs

위에서 보듯 어노테이션을 이용한 DI방법은 여러가지가 있지만 대표적으로 2가지를 설명하자면 @Autowired , @Resource 를 이용한 DI 주입 방법을 들수있다. @Autowired는 해당 변수의 인터페이스 타입으로 등록된 빈들에서 찾아서 DI를 주입해주는 방법이다. 만약 UserService 라는 인터페이스를 구현한 클래스가 2개 이상 빈으로 등록되어있다면 이름의 충돌이 발생해 제대로 DI가 되지 않는 경우가 있다.(에러가 뜬다. 하지만 에러를 발생하지 않게 하려면 @Autowired(require=false) 로주면 에러는 발생하지 않는다.) 변수의 타입으로 판별 할수 없다면 변수명을 이용하여 DI를 한다고 하지만 그 마저 마땅치 않으면 예외가 발생 할 수가 있다. 그래서 사용하는 어노테이션이 @Resource 어노테이션이다. @Resource(name="~") name이라는 속성안에 등록된 빈의 이름을 지정한다면 같은 타입의 인터페이스를 구현한 클래스들이 여러개 등록되어 있더라도 정확히 이름으로 골라서 등록이 가능하다. 하지만 만약 클래스를 @Service,@Component 등의 어노테이션으로 빈등록을 했다면? 방법이 있다. 예를 들어 UserServiceImpl 라는 UserService 인터페이스 구현클래스를 어노테이션으로 빈등록을 했다면 그 빈은 자동으로 userServiceImpl 라는 이름으로 빈등록이 된다. (앞글자를 소문자로) 그래서 내부적으로 지정된 userServiceImpl 라는 이름을 @Resource의 name 속성에 넣어주면 된다. @Autowired로 빈을 결정 지을 수 없을때, 밑에 @Qualifier("~")를 붙여서 특정빈을 선택한다.




2. DI 이전에 필요한 스프링설정


위의 어노테이션들을 사용하여 DI를 주입하기 위해서는 각각 어노테이션을 인식하기 위한 스프링 설정이 필요하다.


1
2
<!-- Root Context: defines shared resources visible to all other web components -->
    <context:component-scan base-package="com.web.nuri"></context:component-scan>
cs

posted by 여성게
: