Spring

Spring프레임워크_chapter03_Dependency Injection

강용민 2022. 3. 17. 21:05

1.Dependency Injection정의

개발 시 하나의 기능을 처리를 수행하기 위하여 여러 개의 컴포넌트를 조합해서 구현하는 경우가 일반적인데,

여러 개의 컴포넌트를 통합할 때 의존 관계 주입(Dependency Injection) 디자인 패턴이 매우 효과적이다.

DI는 오브젝트 간의 의존 관계를 만드는 것으로 객체 간의 결합도를 낮춘다.

방법 1은 A객체가 B와 C객체를 New 생성자를 통해서 직접 생성하는 방법이고,           방법 2는 외부에서 생성 된 객체를 setter()를 통해 사용하는 방법이다.

IoC(Inversion of Control)은 역전 제어, 즉 인스턴스를 제어하는 주도권이 역전된다는 의미이다.

컴포넌트를 구성하는 인스턴스 생성과 의존 관계 연결을 개발자의 소스 코드가 아닌 DI 컨테이너가 대신해 주기 떄문에 제어가 역전되었다고 정의한다.

spring 프레임워크이 제공하는 IoC Container를 통해 인스턴스의 생명주기 관리 및 의존 관계 주입을 처리한다.

Main이 이용하는 Service와 Service가 이용하는 DAO 인스턴스를 DI 컨테이너가 대신 생성 해주고 있으며, DAO 인스턴스를 Service에 의존관계 주입(DI)하고 있다.

DI Container의 활용 : Interface 기반의 컴포넌트화

인터페이스 기반의 컴포넌트화를 실현하려면 MemberService와 MemberDAO를 인터페이스로 만들고 구현 클래스는 Impl을 덧붙인다.

 

Ioc Conatiner에 의해 관리되는 오브젝트들은 Bean이라 부르며, IoC Container는 스프링Bean의 생성, 관계, 조립, 생명주기를 관리하는 Spring 프레임워크의 핵심역할을 하고있다.

Spring 컨테이너의 종류는 BeanFacory와 ApplicationContext가 있다.

Ioc Container는 주로 ApplicationContext를 사용하는데 그 이유는 ApplicationContext가 BeanFactory를 상속받고 있으며, 더 다양한 기능을 가지고 있기 때문이다.

 

2.ApplicationContext와 Bean 정의

BeanFatory는 Bean의 생성, Bean의 의존관계 관리등의 DI의 기본 기능을 제공한다.

Bean이 많지 않고 경량 컨테이너로 작업할 때 활용한다.

ApplicationContext는 일반적인 Spring Container를 의미하며, 위에 말했듯 BeanFactory 인터페이스를 상속받은 하위 인터페이스로 확장된 기능을 제공한다. 

WebApplicationContext는 웹 어플리케이션을 위한 ApplicationContext로 종류는 ContextLoaderListener에 의해 생성되는 RootWAC와 DispathcerServlet에 의해 생성되는 WAC가 있다.

  • ContextLocaderListener에 의해 생성되는 WAC
    • Persistence(DAO), Service 관련 스프링 빈들을 등록
    • 웹 어플리케이션 전체에서 사용할 WAC 객체를 생성
    • ServletContext에 등록된 빈들을 이용 불가능하고 servletContext와 공통된 빈이 있다면 servletContext의 Bean이 우선된다.
    • root-context.xml 파일에 설정
  • DispatcherServlet에 의해 생성되는 WAC
    • DispatcherServlet이 직접 사용하는 컨ㄴ트롤러를 포함한 웹 관련 Bean을 등록하는 데 사용한다.
    • 서블릿 마다 사용할 독자적인 WebApplicationContext를 가지고 있고, 모두 동일한 Root WebApplicationContext를 공유한다.
    • servlet-context.xml 파일에 설정

그러면, DI는 어떻게 설정하는가를 보자면 XML, Annotation, JAVA 기반 설정을 통해서 객체간의 의존 관계를 설정한다.

방법 설명
XML 기반 설정 XML 파일을 사용하는 <Bean> 요소를 정의하는 방법
Annotation 기반 설정 @Component 어노테이션이 부여된 클래스를 DI Container가 Bean으로 자동으로 등록하는 방법
JAVA 기반 설정 자바 클래스에 @Configuration 애노테이션을, 메서드에 @Bean 어노테이션을 사용해 Bean을 등록하는 방법

 

3.XML을 이용한 DI

XML을 이용한 DI방식은 생성자 기반과 설정자 기반으로 나뉜다.

  • 생성자 기반 의존성 주입(Constructor based dependency Injection)
    • 생성자의 인수를 사용해 의존성을 주입
    • 설정파일 XML에 <constructor-arg>태그를 사용하여 주입할 컴포넌트를 설정
  • 설정자 기반 의존성 주입(Setter based dependency Injection)
    • 메서드의 인수를 통해 의존성을 주입
    • 설정파일 XML에 <property>요소의 name속성에 주입할 컴포넌트의 이름을 설정

Bean 태그의 속성은 다음과 같다.

속성 의미
id 오브젝트를 유일하게 하는 ID
name 오브젝트명을 정의
오브젝트에 여러 이름을 설정하고 싶을 때나 ID에는 설정할 수 없는 이름을 지정할 때 이용
class id의 실체. 패키지명과 클래스명으로 구성
scope 오브젝트의 스코프를 지정(singleton, prototype, request, session, apllicatioin)
parent 설정을 물려받을 오브젝트명을 지정
abstract 인스턴스를 만들지 않고 공통설정을 정의해두고 싶을 때 지정
singleton getBEan 메서드로 얻는 인스턴스는 매번 인스턴스화된 것
lazy-init 인스턴스 생성을 지연시킴

 

4.Annotation을 이용한 DI 설정 방법

Annotation은 메타데이터를 XML등의 문서에 설정하는 것이 아니라 소스 코드에 "@annotation"의 형태로 표현한다.

클래스, 메소드, 필드의 선언부에 표현하여 특정 기능이 적용되었음을 알려준다.

종류는 @Autowired와 @Component로 나뉜다.

  • @Autowired
    • Container가 bean과 다른 bean과의 의존성을 자동으로 연결하도록 하는 수단이다.
    • 인스턴스 변수(bean) 앞에 @Autowired 어노테이션을 붙이면 해당 타입의 component(bean)을 찾아 그 인스턴스(bean)을 주입시켜준다.
    • @Autowired 설정을 사용하기 위해서는 <context:annotation-config/>설정이 필요하다. 단 <context:component-scan/>가 설정되어 있으면 생략이 가능하다.
  • @Component
    • Container가 인젝션을 위한 인스턴스(bean)을 설정하는 수단이다.
    • 클래스 선언 앞에 @Component를 붙이면 컨테이너가 찾아서 관리하고 @Autowired가 붙은 인스턴스 변수(bean)에 주입시켜준다.
    • <context:component-scan base-package="패키지이름"/>선언은 @Component 어노테이션이 붙은 클래스를 자동으로 빈으로 등록하는 기능이다.

 

 

[참조]

https://velog.io/@gillog/Spring-DIDependency-Injection

https://velog.io/@jbb9229/springioccontainer

https://doorisopen.github.io/developers-library/Spring/2020-07-23-spring-method-of-di