Spring | 02 스프링의 특징과 의존성 주입

파과·2022년 9월 19일

OOP : 객체 지향 프로그래밍(Object-Oriented Programming)

스프링의 특징

1. POJO 기반의 구성

객체 간의 관계를 구성할 때 별도의 API 등을 사용하지 않는 Plain Old Java Object의 구성만으로 가능하다. → 이는 개발자가 특정 라이브러리나 컨테이너의 기술에 종속적이지 않다는 것을 의미.

2. 의존성 주입

왜 외부에서 객체를 주입하는 방식을 사용하는가? - 주입받는 입장에서 어떤 객체인지 신경 쓸 필요가 없다, 어떤 객체에 의존하든 자신의 역할은 변하지 않는다.

스프링에서는 ApplicationContext 가 필요한 객체들을 생성하고 주입한다. 이렇게 관리되는 객체들을 빈Bean이라고 부르고, 빈과 빈 사이의 의존관계를 xml설정, 어노테이션 설정, 자바 설정 방식 등을 사용해 설정할 수 있다.

3. AOP의 지원

AOP : Aspected Oriented Programming
횡단 관심사(cross-concern)를 모듈로 분리하는 프로그래밍 패러다임.

AspectJ의 문법을 통해 작성한다.

4. 트랜잭션의 지원

하나의 업무가 여러 작업으로 이루어지는 경우의 트랜잭션 처리. 어노테이션이나 xml로 설정할 수 있어 매번 코드를 작성할 필요가 없다.

의존성 주입 테스트

레스토랑 객체를 만들고 레스토랑에서 일하는 셰프 객체를 주입하는 예제.

스프링에서는 의존성 주입을

  • 생성자를 이용한 주입
  • setter 메소드를 이용한 주입

으로 구현한다. 설정방식은 주로 xml이나 어노테이션으로 처리한다.

pom.xml 설정

수정하거나 추가할 부분. (롬복은 이미 01에서 추가함)

주의: log4j 1.2.15에 exclusion이 여러 개 달려있는 전체 태그를 그냥 다 주석처리하고 dependency를 새로 적는다. exclusion 놔두면 오류남.

<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.17</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>${org.springframework-version}</version>
</dependency>

junit 라이브러리를 4.12버전으로 변경했는지 확인한다.

예제 클래스 생성

Chef.java

package org.zerock.sample;

import org.springframework.stereotype.Component;

import lombok.Data;

@Component
@Data
public class Chef {

}

Restaurant.java

package org.zerock.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.Setter;

@Component
@Data
public class Restaurant {

	@Setter(onMethod_ = @Autowired)
	private Chef chef;
}

XML을 이용해 의존성 주입하기

  • root-context.xml의 Namespaces 탭에 context를 체크해 추가한다.
  • Source 탭에서 아래 코드를 추가한다.
<context:component-scan base-package="org.zerock.sample"></context:component-scan>

스프링에서 벌어지는 일

스프링이 시작되면 ApplicationContext 객체가 만들어진다. 이 객체가 관리하는 빈들의 설정이 root-context.xml 파일이다. 이 파일에 설정해놓은 <context:component-scan> 태그에 따라 해당 패키지를 스캔하기 시작한다. 패키지의 클래스들 중 @Component 어노테이션이 존재하는 클래스의 인스턴스를 생성한다. @Autowired(의존성 필요하다는 설정)에 따라 스프링은 Chef객체의 레퍼런스를 Restaurant 객체에 주입한다.

테스트 코드로 확인하기

  • @RunWith : 현재 테스트 코드가 스프링을 실행하는 역할을 할 것이라고 표시
  • @ContextConfiguration : 지정된 클래스나 문자열로 필요한 객체를 스프링 내에 객체로 등록 → 이를 흔히 스프링의 빈으로 등록한다고 말한다. classpath:나 file:을 이용한다.
  • @Log4j는 로그를 기록하는 Logger를 변수로 생성한다.
  • @Autowired는 해당 인스턴스 변수가 스프링으로부터 자동으로 주입해 달라고 하는 표시다. 스프링은 obj변수에 Restaurant 타입의 객체를 주입하게 된다.
  • @Test는 JUnit에서 테스트 대상을 표시하는 어노테이션이다.
    -assertNotNull()은 restaurant 변수가 null이 아니어야만 테스트가 성공한다는 뜻.

테스트 작업은 프로젝트 초기에 설정해 두고 사용하는 것이 좋다.

Run As > Junit Test로 결과 확인

🔗 테스트에서 사용된 주요 어노테이션

생성자를 통한 주입

호텔에서도 Chef가 필요하다고 생각하고 SampleHotel 클래스를 작성해보자.
@Autowired 어노테이션 대신 생성자를 선언하고 Chef를 주입한다.

SampleHotel.java

package org.zerock.sample;

import org.springframework.stereotype.Component;

import lombok.Getter;
import lombok.ToString;

@Component
@ToString
@Getter
public class SampleHotel {

	private Chef chef;
	
	public SampleHotel(Chef chef) {
		this.chef = chef;
	}
}

HotelTests.java

package org.zerock.sample;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class HotelTests {
	@Setter(onMethod_ = { @Autowired })
	private SampleHotel hotel;
	
	@Test
	public void testExist() {
		
		assertNotNull(hotel);
		
		log.info(hotel);
		log.info("------------------------------");
		log.info(hotel.getChef());
	}
}

0개의 댓글