Spring IoC

What is Spring?

자바 기반의 프레임워크 (처리 영역에 따른 구분)

  • Presentation (View)
    • Struts
    • Spring(MVC)
  • Business (Controller)
    • Spring(IoC, AOP)
  • Persistence (Model)
    • Hibernate or JPA
    • Ibatis or Mybatis

Component Model vs POJO

  • Component Model
    • Servlet on Container(Tomcat 등)
    • MobileApp on Container(Android)
    • 등등

POJO란? Plain Old Java Object의 약자로, 평범한 옛날 자바 객체를 의미함. 규칙대로 작성해야하는 Servlet과 반대됨. Spring의 가장 큰 특징 중 하나로, 기존에 만들었던 클래스를 Spring의 Container 위에서 별 다른 수정없이 실행 가능. => 재사용성이 증가

Spring Framework의 장점

  • 경량
  • IoC(Inversion of Control) : 제어의 역행 -> 낮은 결합도(아래에 자세히 정리)
  • AOP(Aspect Oriented Programming) : 공통으로 사용하는 기능들을 외부의 독립된 클래스로 분리하고, 해당 기능을 프로그램 코드에 직접 명시하지 않고 선언적으로 처리하여 적용하는 것.

IoC(Inversion of Control) 컨테이너

IoC란?

  • 제어의 역전
  • 객체의 생성이나, 메소드의 호출이 개발자가 아닌 외부에 의해 결정되는 것.
  • 개발자가 의도한대로 흘러가는 프로그램이 아닌, 사용하고자 하는대로 사용가능한 프로그램.
  • 모델 간 결합도가 낮추는 패턴이자, 컨테이너

뜬금없지만.. Eclipse에서 Spring 프로젝트를 만드는 방법

  1. Project 생성
  2. Spring Nature 주입
  3. Maven으로 Spring Library 추가
    • pom.xml (필요한 라이브러리 나열)
    • Maven에서 자동으로 라이브러리 설치

Spring Container(IoC 컨테이너)의 동작 순서

  1. 클라이언트(User)가 Spring 설정 파일을 로딩하여 컨테이너 구동.
  2. Container는 Spring Bean Configuration File에 등록된 Bean 생성.
    • ApplicationContext 클래스로 만들어진 Container -> Pre-loading이 default
    • BeanFactory 클래스로 만들어진 Container -> Lazy-loading이 default
    • 바꾸고 싶다면, bean 태그에 lazy-init 속성을 “true”, “false”로 바꾸어주면됨.
  3. getBean() 메소드로 객체 요청(Lookup)
  4. 객체(POJO) 반환

Application Context의 구현 클래스

  • GenericXmlApplicationContext : 파일 시스템 혹은 클래스 경로에 있는 XML 설정 파일을 로드하여 구동하는 컨테이너.
  • XmlWebApplicationContext : 웹 기반의 스프링 어플리케이션을 개발할 때 사용하는 컨테이너

Spring XML 파일

bean 저장소에 해당하는 Spring Bean Configuration File을 참조하여 bean의 생명주기를 관리하고, 서비스를 제공함. -> 프로젝트에 전체적으로 가장 중요한 역할이므로, 정확하게 작성하고 관리하는 것이 중요함.

<import> Elemenet

  • bean을 등록하는 것 이외에도 트랜잭션 관리, 예외처리, 다국어 처리 등 복잡하고 다양한 설정이 필요함.
  • 관리 효율을 위하여 분할하여 작성한 XML파일들을 import하여 한 파일로 합치는 효과를 낼 수 있음 <bean> Elemenet
  • 클래스를 등록하는데 사용되는 element
  • Fields
    • class : 필수 / 정확한 경로와 패키지 이름으로 지정
    • 클라이언트(App, Test 등) 에서 객체를 요청(Lookup)하려면 반드시 이름이 필요함. 아래는 이름으로 사용가능한 속성.
      • id :
      • name :
    • init-method : 객체의 생성(생성자 호출) 이후, 멤버변수 초기화 등이 필요할 때 호출될 메소드를 지정.
    • destroy-method : 객체가 삭제되기 직전에 호출될 메소드 지정
    • lazy-init : bean들을 컨텍스트 구동시점이 아닌 해당 bean이 사용되는 시점에 생성하도록 변경하는 속성
      • default : 사용하는 컨테이너의 default를 따름
      • false : Pre-loading방식(ApplicationContext의 default)
      • true : lazy-load 방식(BeanFactory의 default)
    • scope : bean을 사용하여 생성된 객체를 어느 범위까지 사용하는지 지정하는 속성
      • singleton : GoF 디자인 패턴 중 하나인 싱글톤 패턴. 단 하나의 객체만 스프링 컨테이너에 생성되어 운용되도록 하는 것.
      • prototype : bean이 요청될 때마다, 매 번 새로운 객체를 생성하는 것.
      • request
      • session
      • global session

의존성 주입 (Dependency Injection)

의존성 관리

Spring은 객체의 생성과의존관계를 컨테이너가 자동으로 관리함. -> IoC의 핵심 원리

IoC의 두 가지 지원 형태

  • Dependency Lookup
    • 의존성 검색
    • IoC 컨테이너에 존재하는 객제 저장소(Pool)에서 객체를 검색하여 참조하는 방법.
    • 컨테이너가 제공하는 API(getBean() 등)를 이용하여 의존성 객체 획득
    • Dependency Pool
    • Contextualized Dependency Lookup
  • Dependency Injection
    • 의존성을 외부에서 결정하도록 하는 방법
    • Lookup과의 차이점
      1. Lookup은 Pool에서 검색해온 객체를 코드상에서 직접 의존성 발생시킴
      2. Injection은 별도파일(xml)을 이용하여 bean의 property 혹은 constructure-args로 지정
    • Lookup보다 훨씬 유연하고 간단한 방법 -> 별도 파일을 통해 의존성을 주입하기 때문에, 소스코드의 변경 없이 주입 타겟 변경이 가능.
    • Construction Injection
    • Setter Injection

의존성 관리를 사용하는 이유

  • 의존관계가 있는 객체 객체 생성 코드를 메소드에서 호출할 경우
    • 호출될 때마다 각자 다른 객체 생성
    • 기존 Class를 다른 Class로 바꾸기 위해서는 의존관계에 있는 Class의 코드(객체 생성코드가 들어있는 메소드)도 수정해야함.
    • 위와 같은 문제가 있음.
  • Spring에서는 이를 의존성 주입을 이용하여 해결함.

Annotation

Annotation이란?

  • Java 코드에 추가하여 사용할 수 있는 메타데이터의 일종
  • JDK 1.5 버전 이상에서 사용 가능
  • Annotation은 클래스 파일에 삽입되어 컴파일러에 의해 생성된 후 자바 가상머신에 포함되어 작동한다.

Annotation의 기능

  • 컴파일러에게 코드 문법 에러를 체크하도록 정보 제공
  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
  • 실행 시(런타임 시) 특정 기능을 실행하도록 정보 제공

    Spring에서의 Annotation

    XML에 Context 관련 네임스페이스를 추가하여 어노테이션을 이용한 bean등록 및 의존성 주입이 가능하다.

component-scan 설정 bean을 하나하나 등록하지 않고, 패키지를 스캔하여 자동으로 생성하기 위한 Element

<context:component-scan base-package="com.example"></context:component-scan>
<!-- com.example 패키지를 스캔하여 bean을 자동으로 등록 -->

Bean 등록하기

  • @Component <context:component-scan>을 이용하여 스캔할 때 bean으로 등록할 대상 Class를 지정하는 annotation

Component 외에도 많은 annotation이 bean 등록을 지원한다. 자세한건 해당 파트에 가서 정리하는걸로…

@Component("ltv") // 괄호 안은 bean의 id 지정
public class LTV implements TV{
    public LTV(){
        ...
    }
}

id나 name 속성 미지정 시 Lookup할 때 이름은 클래스 이름의 앞 글자를 소문자로 바꾸면 됨. (ex. class LTV -> lTV)

의존성 주입 설정

의존성 주입을 지원하는 Annotation들

  • @Autowired 해당 변수 위에 설정하여 해당 타입의 객체를 찾아서 자동으로 할당(Spring 기본 제공)
  • @Qualifier 특정 객체의 이름을 이용하여 의존성 주입 시 사용 (Spring 기본 제공)
  • @Inject @Autowired와 동일한 기능 (Spring 기본 X)
  • @Resource @Autowired와 @Qualifier의 기능을 결합 (Spring 기본 X)

의존성 주입에 있어서 XML 설정과 Annotation 설정은 장단점이 상충함.

  • XML
    • Java 코드를 수정하지 않고, XML만 변경하면 의존관계를 변경 가능. -> 유지보수가 편함.
    • XML 설정 자체의 복잡함, 부담
    • Java 코드에 의존관계와 관련된 어떠한 메타데이터가 없으므로 XML 설정을 해석해야 의존성 확인 가능.
  • Annotation
    • XML 부담 X
    • 의존관계에 대한 정보를 Java 코드에서 확인 가능. -> 사용하기 편함
    • 의존관계 변경 시 Java 코드를 변경해야함.

결론

둘 다 섞어서 쓰자.

변경되지 않는 객체는 Annotation 설정 -> 쉽게 작성 가능 변경될 가능성이 있는 객체는 XML 설정 -> 유지보수 편함

라이브러리 형태로 제공되는 클래스는 반드시 XML 설정을 통해서만 사용 가능