본 글은 스터디 내에서 전문가를 위한 스프링5를 읽고 정리한 글입니다.
3.1 Ioc와 DI
의존 객체: 의존성이 필요한 컴포넌트 -> Ioc에서는 대상(target)이라고 함
IOC : 의존성 주입(DI), 의존성 룩업(DL)로 나눌수 있음.
3.2 Ioc와 종류
의존성 룩업: 컴포넌트 스스로 의존성의 참조를 가져와야 함(의존성 풀, 의존성 룩업)
의존성 주입: Ioc 컨테이너가 컴포넌트에 의존성을 주입함(생성자, 수정자 의존성 주입)
3.2.1 의존성 풀
필요에 따라 레지스트리에서 의존성을 가져오게 됨
package com.example.prospring5;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DependencyPull {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/app-context.xml");
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
3.2.2 의존성 룩업
자원을 관리하는 컨테이너에서 의존성을 가져옴.
컴포넌트는 컨테이너 인터페이스를 구현해 의존 관계를 얻으려는 컨테이너에 신호를 보냄.
컨테이너가 컴포넌트에 의존성 전달될 준비가 되면, 컨테이너는 performLookup() 메서드를 호출함.
package com.example.prospring5;
public class ContextalizedDependencyLookup {
private Dependency dependency;
public void performLookup(Container container) {
this.dependency = (Dependency) container.getDependency("myDependency");
}
}
3.2.3 생성자 의존성 주입
컴포넌트의 생성자(또는 여러 생성자)를 이용해서 해당 컴포넌트가 필요로하는 의존성을 제공하는 방식
package com.example.prospring5;
public class Constructioninjection {
private Dependency dependency;
public Constructioninjection(Dependency dependency) {
this.dependency = dependency;
}
}
3.2.4 수성자 의존성 주입
자바빈 방식의 수정자 메서드를 이용해 컴포넌트의 의존성을 주입함.
package com.example.prospring5;
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
3.2.5 의존성 주입 vs 의존성 룩업
스프링에서는 초기 빈 룩업을 제외하면 컴포넌트와 의존성은 항상 의존성 주입 방식의 Ioc를 이용해 연결됨.
의존성 주입과 의존성 룩업 중 무엇을 선택해야 될까?
-> 의존성 주입
1. 컴포넌트에 어떠한 코드 변화를 일으키지 않음
2. 사용자 클래스는 협력 객체를 의존 객체에게 제공하는 Ioc 컨테이너와 완전히 분리돼 자유롭게 사용 가능
3. 테스트용 의존성을 쉽게 제공 가능
4. 작성하는 코드량이 줄고, 자동화 가능
5. 객체가 필드에 저장되어 의존성을 가져오는 코드가 전혀 필요하지 않음
3.2.6 수정자 주입 vs 생성자 주입
생성자 주입은 컴포넌트 사용 전에 해당 컴포넌트의 의존성을 반드시 갖고 있어야 할 때 유용
생성자 주입을 사용하면 빈 객체를 불변 객체로 사용 가능.
수정자 주입은 컴포넌트가 의존성을 컨테이너로 노출하지만, 의존성을 제공할때는 제일 좋은 방법
-> 인터페이스에서 모든 의존성을 선언 가능
수정자 의존성 주입 방법
비지니스 인터페이스에서 의존성을 정의할 필요가 없음.
주입을 위한 수정자가 사용자 인터페이스의 외부에 존재하도록 해야함.
(구현 클래스 각각이 자신의 의존성을 각자 정의하고, 비지니스 인터페이스에는 비지니스 메서드만 유지해야 함)
package com.example.prospring5;
public interface Oracle {
String defineMeaningOfLife();
}
package com.example.prospring5;
public class BookwormOracle implements Oracle{
private Encyclopedia encyclopedia;
public void setEncyclopedia(Encyclopedia encyclopedia) {
this.encyclopedia = encyclopedia;
}
@Override
public String defineMeaningOfLife() {
return "아무거나";
}
}
구성 인자와 구성 인자가 아닌 의존성 사이의 차이점?
1. 구성 인자는 수동적
2. 구성 인자는 일반적으로 어떤 컴포넌트가 아니라 정보 자체.
3. 구성 인자는 단순한 값이거나 단순한 값들의 컬렉션
3.3 스프링의 제어 역전
스프링은 의존 객체에 협력 객체를 자동으로 제공하기 위해 의존성 주입 이용
스프링은 의존성 주입만으로 모든 애플리케이션 컴포넌트를 자동 연결 불가
의존 객체에 접근하려면 -> 의존성 룩업이 필요
스프링 MVC에서는 스프링이 애플리케이션 전체를 자동으로 연결하므로 의존성 룩업 필요 없음
3.4 스프링의 의존성 주입
3.4.1 빈과 빈 팩터리
BeanFactory는 컴포넌트의 라이프사이클뿐만 아니라 의존성 관리
빈: 컨테이너가 관리하는 모든 컴포넌트
애플리캐이션에서 DI 기능이 필요하다면 BeanFactory 인터페이스를 이용해 스프링 DI 컨테이너와 직접 연동 가능
이때는 애플리케이션에서 BeanFactory 인터페이스를 구현한 클래스의 인스턴스를 생성하고 빈과 의존성 정보 구성
-> BeanFactory 구성을 프로그래밍으로 할 수도 있지만, 구성 파일을 사용해 외부에서 구성하는 방법이 일반적
BeanFactory 구현 클래스는 BeanDefinitionReader 인터페이스를 구현하고, BeanDefinition 데이터를 읽을 수 있음.
-> 사용자는 BeanFactory 내에서 사용자 빈 식별 가능(각 빈에 ID 혹은 이름으로 지정)
-> 빈 ID나 이름을 사용해 빈을 가져와 의존성 확립 가능
스프링 내부에서 빈 구성은 BeanDefinition 인터페이스를 구현한 클래스의 인스턴스로 표현한다.
3.4.2 BeanFactory 구현체
스프링 빈 구성 파일은 Id, 이름을 빈에 지정하고 빈의 구현체를 명시함.
BeanFactory 인터페이스를 구현한 클래스를 상속받고, 원하는 로직을 추가하여 새로운 구성 매커니즘 생성
3.4.3 애플리케이션 컨텍스트(ApplicationContext)
ApplicationConteddxt 인터페이스는 BeanFactory를 상속한 인터페이스
DI, AOP, 트랜잭션 서비스, 국제화를 위한 메시지 소스 제공
'📗 BOOK > 전문가를 위한 스프링5' 카테고리의 다른 글
Spring 테스트 코드 적용하기(JUnit, TDD) (0) | 2022.04.28 |
---|---|
전문가를 위한 스프링5 - 3장 정리(2) (0) | 2022.02.27 |