Formoat's Open Blog
DI (Dependency Injection) - 의존성 주입 본문
# IoC(Inversion of Control)
IoC란 직역하면 제어의 역전, 의존적 주입이라고 할 수 있다.
자바 기반의 어플리케이션에서 자바 객체를 생성하고 객체간 의존 관계를 연결시키는 작업의 제어권은 보통
개발되는 어플레케이션 즉 내부에 있다. 하지만 스프링에서는 이 제어권을 내부가 아닌 외부(컨테이너)에서
전담하게된다. 스프링 설정파일에 등록된 정보들을 바탕으로 처리하게 되는데 이것을 제어의 역전이라고 한다.
Dependency Lookup : 컨테이너가 애플리케이션 운용에 필요한 객체를 생성하고 클라이언트는 컨테이너가 생성한
객체를 검색(Lookup)하여 사용하는 방식 → 실제 애플리케이션 개발에는 사용하지 않음.
Dependency Injection : 객체 사이의 의존 관계를 자기 자신이 아닌 외부(Container)에 의해서 설정. 즉 스프링 설정
파일에 등록된 정보를 바탕으로 컨테이너가 자동으로 처리해 줌.
# 스프링 컨테이너의 종류
1) BeanFactory
- 스프링 설정 파일에 등록된 <bean> 객체를 생성하고 관리하는 가장 기본적인 컨테이너.
- 클라이언트의 요청(lookup)에 의해서만 bean 객체를 생성함.
2) ApplicationContext
- BeanFactory 제공하는 기능 외에, 트랜잭션 관리, 메시지 기반의 다국어 처리 등 다양한 기능을 제공.
- bean에 등록된 클래스들을 객체 생성하는 즉시 로딩 방식으로 동작
3) GenericXmlApplicationContext
- 파일 시스템이나 클래스 경로에 있는 XML 설정 파일을 로딩하여 구동하는 컨테이너
4) GenericGroovyApplicationContext
- 그루비 코드를 이용해 설정 정보를 가져온다.
# XML DI (XML을 이용한 의존성 주입)
1) Constructor Injection
2) Setter Injection
# Java Annotation DI (어노테이션 의존성 주입)
Annotation | Description |
@Autowired | 주로 변수 위에 설정하여 해당 타입의 객체를 자동으로 할당 |
@Qualifier | 특정 객체의 이름을 이용해 의존성 주입할 때 사용 |
@inject | @Autowired와 동일한 기능을 제공 |
@Resource | @Autowired, @Qualifier의 기능을 결합 |
어노테이션을 사용하려면 먼저 어노테이션을 활성화 시키는 작업을 해야한다.
// applicationContext.xml 파일에 네임 context 네임 스페이스를 추가하고 활성화 코드를 입력
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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-4.3.xsd">
<!-- 어노테이션 활성화 -->
<context:annotation-config/>
</beans>
1) @Autowired - 생성자, 필드, 메소드 세 곳에서 사용이 가능하며 주로 필드에 사용된다.
# 동작순서
- @Autowired를 스프링 컨테이너가 확인하는 순간 해당 변수의 타입을 체크한다.
- 체크한 타입의 객체가 메모리에 존재하는지 여부를 확인 (context.xml)
- 객체가 존재한다면 어노테이션이 사용된 변수에 객체를 주입한다.
※ 예외사항
체크한 타입의 객체가 메모리에 존재하지 않는다면 NoSuchBeanDefinitionException을 발생시킨다.
체크한 타입의 객체가 여러개일 경우 NoUniqueBeanDefinitionException을 발생시킨다.
2) @Qualifier - 의존성 주입 대상의 객체가 여러개일 때 범위를 좁히는데 사용된다.
위의 @Autowired 어노테이션의 예외발생 상황인 체크한 타입의 객체가 여러개일 경우 사용이 되며,
의존성을 주입하는 다른 어노테이션과 같이 사용이 된다.
// 사용 예) @Qualifier("생성된 객체 ID")
3) @Resource - @Autowired, @Qualifier의 기능을 결합한 형태이다.
// 사용 예) @Resource(name="생성된 객체 ID")
# Component Scan (빈 자동 등록)
- 특정 패키지에 위치한 클래스를 스프링 빈으로 자동 등록한다. (context.xml)
- 자동 등록을 위해 검색하는 대상은 '@Component'가 붙은 클래스이다.
@Component를 이용하면 해당 클래스의 객체를 생성할 수 있지만 문제점은 해당 객체가
어떠한 역할(로직)을 수행하는지 파악하기 어렵다. 때문에 스프링에서는 @Component를
상속받는 어노테이션들이 추가적으로 몇가지 존재한다.
Annotation | -- | Description |
@Service | XXXServiceImpl | 비즈니스 로직을 처리하는 Service 클래스 |
@Repository | XXXDAO | 데이터베이스 연동을 처리하는 DAO 클래스 |
@Controller | XXXController | 사용자 요청을 제어하는 Controller 클래스 |
※ Component, Service, Repository, Controller 등 빈을 등록해주는 어노테이션 사용시 빈의 이름을
설정하지 않을는다면 기본값으로 클래스이름으로 등록된다. (단, 이름의 첫번째 알파벳은 소문자)
// 예: SamsungTV → samsungTV