본문 바로가기

Web[웹]/Spring Framework

[Spring] 의존객체 자동 주입 : @Autowired와 @Resource

 

의존 객체 자동 주입

 

의존객체 자동 주입은 스프링 설정 파일에서 의존 객체를 주입할 때 <constructor-org> 또는 <property> 태그로 의존 대상 객체를 명시하지 않아도 스프링 컨테이너가 자동으로 필요한 의존 대상 객체를 찾아서 의존 대상 객체가 필요한 객체에 주입해 주는 기능이다. 구현 방법은 @Autowired와 @Resource 어노테이션을 이용해서 쉽게 구현할 수 있다.

 

1. @Autowired

@Autowired는 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입한다.

 

· @Autowired 사용 전

public class BookService {
    private BookRepository bookRepository;
    
    public BookService(BookRepository bookRepository){
        this.bookRepository = bookRepository;
    }
}

 

BookService Class는 생성자로 BookRepository를 전달받고 인스턴스 변수에 할당하는 코드를 가지고 있다.

 

<?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="bookRepository" class="com.kim.service.bookRepository" />

    <bean id="bookService" class="com.kim.service.BookService">
        <constructor-arg ref="bookRepository" />
    </bean>
</beans>

BookService에 BookRepository를 주입하기 위해서 XML 파일에 다음과 같이 <constructor-arg> 설정을 해줘야 한다.

 

 

· @Autowired 사용 시

public class BookService {
    private BookRepository bookRepository;
    
    @Autowired
    public BookService(BookRepository bookRepository){
        this.bookRepository = bookRepository;
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" <!--추가-->
	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
 		http://www.springframework.org/schema/context                      <!--추가-->
 		http://www.springframework.org/schema/context/spring-context.xsd"> <!--추가-->
        
    <context:annotation-config /> <!--추가-->

    <bean id="bookRepository" class="com.kim.service.BookRepository" />
    <bean id="bookService" class="com.kim.service.BookService" />
</beans>

객체의 의존성을 가지는 부분에 @Autowired를 사용하고, xml파일에 네임스페이스와 스키마만 추가해주면 향후엔 계속해서 <constructor-arg> 설정 없이 쉽게 의존성을 주입받을 수 있다.

 

그러나 @Autowired는 생성자 위에만 명시할 수 있는 것은 아니다, 프로퍼티와 메서드 위에도 명시가 가능한데 단, 이때는 반드시 디폴트 생성자를 명시해줘야 한다.

 

public class BookService {
	
    @Autowired
    private BookRepository bookRepository;
    
    public BookService(){ /* 디폴트 생성자 추가 */
    
    }
    
    public BookService(BookRepository bookRepository){
        this.bookRepository = bookRepository;
    }
    
    @Autowired
    public void setBook(Book book){
    	this.book = book;
    }
}

 

 

2. @Resource

@Resource는 주입하려고 하는 객체의 이름이 일치하는 객체를 자동으로 주입한다. @Autowired는 생성자, 프로퍼티, 메소드에 다 사용할 수 있는 반면, @Resource는 프로퍼티와 메소드에만 사용이 가능하다. 이 역시도 디폴트 생성자가 필요하다.

 

public class BookService {
	
    @Resource
    private BookRepository bookRepository;
    
    public BookService(){ /* 디폴트 생성자 추가 */
    
    }
    
    public BookService(BookRepository bookRepository){
        this.bookRepository = bookRepository;
    }
    
    @Resource
    public void setBook(Book book){
    	this.book = book;
    }
}

 

 

즉, @Autowired는 "BookRepository bookRepository" 구문에서 타입인 BookRepository를 찾아서 들어가고, @Resource는 이름인 bookRepository를 찾는다.

 

 


 

 

의존객체 선택

 

다수의 빈(Bean) 객체 중 의존 객체의 대상이 되는 객체를 선택하는 방법에 대해서 알아보자.  어노테이션으로만 자동적으로 객체를 주입할 경우 컨테이너에서 주입할 대상이 여러 개여서 의존성을 주입하지 못하는 경우가 발생할 수 있다.  즉,
동일한 객체가 2개 이상인 경우 스프링 컨테이너는 자동 주입 대상 객체를 판단하지 못해서 Exception을 발생시킨다.

 

1. @Autowired - @Qualifier

@Autowired
private Book book;
<bean id ="book1" class ="com.kim.service.Book" />
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />

 

판단하지 못하는 상황은 위와 같은 경우인데, 이 경우 @Qualifier 어노테이션을 써서 하나의 의존객체를 선택하여 객체 간 선택적 충돌이 발생하지 않게 할 수 있다.

 

@Autowired
@Qualifier("usedBook")
private Book book;
<bean id ="book1" class ="com.kim.service.Book" >
	<qualifier value ="usedBook" />
</bean>
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />

 

2. @Inject - @Named

@Inject는 자동주입을 하려는 경우 객체가 생성되지 않아서 주입을 하지 못하는 경우에 사용한다.

 

@Autowired // Exception 발생
private Book book;
<!-- <bean id ="book" class ="com.kim.service.Book" /> -->

 

물론 @Autowired에 "@Autowired(required = false)"라고 바꿔주면 Exception 발생하는 것을 막을 수는 있지만, 잘 쓰지 않는다. 그래서 이와 똑같은 역할을 하는 @Inject를 사용해볼 것이다. 방법은 @Autowired와 거의 똑같다.

 

@Inject
@Named(value="book1")
private Book book;

 

<bean id ="book1" class ="com.kim.service.Book" />
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />

 

위에서 사용한 @Named는 @Autowired에서 @Qualifier과 같은 역할을 하며, 이를 사용할때는 따로 빈(Bean) 설정에 추가할 필요가 없다. 훨씬 간편하게 Exception을 피할 수 있다. 

 

@Autowired와 @Inject 중 @Autowired가 실무에서 가장 많이 쓰이지만, 적절히 활용하면 좋은 코드가 나올 수 있을 것이다.