티스토리 뷰
1. 스프링의 DI(의존성 주입)에서 의존성이란
- 의존성 주입이란 코드 내부에서 객체 간의 연결을 이루는 것이 아니라, 외부에서 설정을 통해서 객체를 연결하는 패턴이다.
- + 즉, A객체에서 B객체를 직접 생성하는 방법이 아니라
- + A는 B가 필요하다는 신호만 보내고, B객체를 주입하는 것은 외부( 스프링 )에서 이루어지는 방법이다.
- + 스프링의 경우 의존성 주입을 쉽게 적용할 수 있는 프레임워크가 존재한다.
- 이때 의존성을 나타낼 수 있는 예시로는 Restaurant -------- > 요리사( chef )로 표시할 수 있다.
- + 이는 요리사 없이는 Restaurant이 존재할 수 없다는 의미이다.
- + Restaurant의 입장에서는 요리사가 반드시 필요하다는 의미이기도 하다.
- [ 기존 버전 ]
- Public class Restaurant {
-
- // 필드의 종류 3가지 : 1.객체의 고유속성, 2.객체의 상태, 3.부품(집합) 관계
- Private Chef chef;
-
- // 생성자( 생성자를 통한 의존성 주입 ) : 초기화
- Public Restaurant ( Chef chef ) {
- this.chef = chef; // 생성자를 통한 의존성 주입 ( DI )
- } // Restaurant ( )생성자
-
- } // Restaurant
- [ 스프링 버전 ]
- Public class Restaurant {
-
- // 필드의 종류 3가지 : 1.객체의 고유속성, 2.객체의 상태, 3.부품(집합) 관계
- @Autowired
- Private Chef chef;
-
- } // Restaurant
- + 스프링에서는 @Autowired를 통해 의존성 주입을 자동으로 요청할 수 있다.
- + 즉, 스프링에서는 개발자가 직접 생성자를 만들지 않아도 @Autowired를 통해 스프링( 스프링 컨텍스트 )에게 객체 주입 신호를 보내서 객체를 주입 받을 수 있다는 의미이다.
- + 컴파일이 아닌 실행시에 의존 관계가 완성되는 방식이다.
- + @Autowired는 생성자 위에도 붙여서 사용할 수 있다.
2. 마이바티스와 Quartz와 스프링
- 마이바티스 : SQL 처리 프레임 워크
- Quartz : Job 스케줄링
- 스프링 :
- + 이전의 EJB( 분산 병렬 컴포넌트 )가 기술 스펙이 너무 난해하고, 구현이 너무 어려워서 이를 해결하기 위해 Spring이 등장했다.
- + 스프링( Spring )은 EJB를 대체하기 위한 경량형( 구현하기 쉬운 ) 분산 병렬 컴포넌트로 구현하기 쉬운 프레임 워크로 등장했으나, 현재는 경량형에서 거리가 멀어지는 중이다.
3. 클래스가 자바빈즈 클래스가 되기 위해 지켜야 하는 규약 4가지
- 1 ) 모든 필드는 private이어야 한다. ( OOP의 은닉화 / 캡슐화 성질 ) -> 필수
- 2 ) 각 필드에 대해서 Getter / Setter 메소드를 가져야 한다. -> 필수
- 3 ) Default Constructor(매개변수가 없는 기본 생성자)를 가져야 한다. -> 필수
- 4 ) java.io.Serializable 태그 인터페이스를 implements(구현)해야 한다. -> 선택
- + 자바빈즈 클래스로부터 생성한 객체를 아래와 같이 부른다.
- + (1) 자바빈즈 객체 -> 축약형 : 자바빈 -> 축약형 : 빈
- + 스프링이 의존성 주입(DI)을 하기 위해서는 기본적으로, Spring Context라는 박스 안에 있는 모든 객체가 빈객체이어야 한다. (***)
- + 그렇기에 Spring Context를 다른 말로 beans container이라고도 한다.
4. @Component
- 자바빈즈 클래스의 타입선언부 위에 @Component 어노테이션을 붙이면, 이 클래스로부터 생성될 빈 객체는 Spring의 Beans Container에 저장될 객체임을 의미한다.
- 이 @Component 어노테이션이 불은 모든 자바빈즈 클래스를 한번에 스프링의 빈으로 설정하기 위해서는 root-context.xml 파일에서 <context:component-scan base-package="범위지정(ex.org.zerock.myapp)" /> 태그를 통해 설정할 수 있다.
[ 1. Spring - 의존성 주입 (DI) ] (****)
[ 1 - 1. chef 클래스 만들기 ]
[ + 코드 보기 ]
import org.springframework.stereotype.Component;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
@ToString
@Log4j2
@NoArgsConstructor
@Component("chef")
public class Chef {
// =====================================================================================
// 자바빈즈 클래스가 되기 위해서는
// - 1 ) 모든 필드는 private이어야 한다. ( OOP의 은닉화 / 캡슐화 성질 ) -> 필수
// - 2 ) 각 필드에 대해서 Getter / Setter 메소드를 가져야 한다. -> 필수
// - 3 ) Default Constructor(매개변수가 없는 기본 생성자)를 가져야 한다. -> 필수
// - 4 ) java.io.Serializable 태그 인터페이스를 implements(구현)해야 한다. -> 선택
// =====================================================================================
// + 다음과 같은 4가지를 지켜야 하지만,
// + 세프 클래스의 경우 필드가 존재하지 않기에 1번과 2번이 자동으로 통과되고
// + @NoArgsConstructor로 Default Constructor를 자동 생성해주었기에 자바빈즈 클래스가 된다.
// =====================================================================================
;;
} // Chef
[ 1 - 2. Restuarant 클래스 만들기 ]
[ + 코드 보기 ]
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@ToString
@Getter(AccessLevel.PUBLIC)
@NoArgsConstructor
@Component("hotel")
// @Component는 빈 컨테이너에 들어가는 구성요소라는 의미이다.
// 사실 ()안에 지정해 주지 않고 @Component만 작성해도 된다.'
public class Hotel {
// =====================================================================================
// 자바빈즈 클래스가 되기 위해서는
// - 1 ) 모든 필드는 private이어야 한다. ( OOP의 은닉화 / 캡슐화 성질 ) -> 필수
// - 2 ) 각 필드에 대해서 Getter / Setter 메소드를 가져야 한다. -> 필수
// - 3 ) Default Constructor(매개변수가 없는 기본 생성자)를 가져야 한다. -> 필수
// - 4 ) java.io.Serializable 태그 인터페이스를 implements(구현)해야 한다. -> 선택
// =====================================================================================
// + 다음과 같은 4가지를 지켜야 하지만,
// + 호텔 클래스의 경우 의존성 객체를 주입받을 필드가 private로 되어있으며,
// + @Getter와 @Setter로 Getter / Setter 조건을 만족시켰고,
// + @NoArgsConstructor로 Default Constructor를 자동 생성해주었기에 자바빈즈 클래스가 된다.
// =====================================================================================
@Setter(onMethod_ = {@Autowired}) // spring Context에게 의존성 주입 시그널 전송
// + 이는 Setter메소드 위에 @Autowired를 만들어달라는 의미이다.
private Chef chef;
} // Hotel
[ 1 - 3. Hotel 클래스 만들기 ]
[ + 코드 보기 ]
package org.zerock.myapp.sample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@ToString
@Getter(AccessLevel.PUBLIC)
@NoArgsConstructor
@Component("hotel")
// @Component는 빈 컨테이너에 들어가는 구성요소라는 의미이다.
// 사실 ()안에 지정해 주지 않고 @Component만 작성해도 된다.'
public class Hotel {
// =====================================================================================
// 자바빈즈 클래스가 되기 위해서는
// - 1 ) 모든 필드는 private이어야 한다. ( OOP의 은닉화 / 캡슐화 성질 ) -> 필수
// - 2 ) 각 필드에 대해서 Getter / Setter 메소드를 가져야 한다. -> 필수
// - 3 ) Default Constructor(매개변수가 없는 기본 생성자)를 가져야 한다. -> 필수
// - 4 ) java.io.Serializable 태그 인터페이스를 implements(구현)해야 한다. -> 선택
// =====================================================================================
// + 다음과 같은 4가지를 지켜야 하지만,
// + 호텔 클래스의 경우 의존성 객체를 주입받을 필드가 private로 되어있으며,
// + @Getter와 @Setter로 Getter / Setter 조건을 만족시켰고,
// + @NoArgsConstructor로 Default Constructor를 자동 생성해주었기에 자바빈즈 클래스가 된다.
// =====================================================================================
@Setter(onMethod_ = {@Autowired}) // spring Context에게 의존성 주입 시그널 전송
// + 이는 Setter메소드 위에 @Autowired를 만들어달라는 의미이다.
private Chef chef;
} // Hotel
[ 1 - 4. root-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 https://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">
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- 여기 안에 속한 것은 모두 빈 타입으로 등록하겠다는 의미이다. -->
<context:component-scan base-package="org.zerock.myapp.sample" />
</beans>
[ + 빈이 등록된 것을 확인 ]
[ 1 - 5. pom.xml파일 수정 - Spring 부분에서 spring-text 추가 ] (***)
[ + 코드 보기 ]
<!-- ================ Spring (밑의 2개는 최소한 꼭) =============== -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
<scope>test</scope>
</dependency>
[ 1 - 6. 실행 클래스에서 의존성 확인해 보기 ] (****)
[ + 코드 보기 ]
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.zerock.myapp.sample.Hotel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
// Lombok's annotation
@Log4j2
@NoArgsConstructor // JUNIT 테스트 클래스의 필수 사항
//================================================
// For JUnit 5 (***)
// JUnit 테스트 메소드 수행시, Spring FrameWork를 함께 구동시키는 구동자 설정
// @ExtendWith는 스프링 프레임워크 구동하는 클래스 지정
@ExtendWith(SpringExtension.class)
//================================================
// For JUnit 4
// JUnit 테스트 메소드 수행시, Spring FrameWork를 함께 구동시키는 구동자 설정
// @RunWith(SpringJUnit4ClassRunner.class)
// @RunWith(SpringRunner.class)
//================================================
//================================================
// JUnit4와 5에서 모두 공통으로 함께 실행될 Spring FrameWork의 설정파일을 알려주는 역할
// file로 지정하면 절대 경로가 아니라 프로젝트 아래의 파일을 확인하게 된다.
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/spring/**/*.xml" })
//================================================
// JUnit-jupiter's annotation
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class DiBySetterTests {
// @BeforeAll
// void beforeAll() {}
// 의존성 주입(DI)
@Autowired
private Hotel hotel;
// ================================================
// JUnit5에서는 자유롭게 이름을 작성해도 된다.
// ================================================
@Test
@DisplayName("contextLoads")
@Order(1)
@Timeout(value=1000, unit = TimeUnit.MILLISECONDS)
void contextLoads() {
log.trace("contextLoads() invoked.");
Objects.requireNonNull(this.hotel);
log.info("\t + this.hotel : {}", this.hotel);
// + this.hotel : Hotel(chef=Chef()) ( 호텔 객체가 들어왔음을 알 수 있다. )
// + 호텔 객체 빈 안에도 세프 객체 빈이 필드로 주입된 것을 알 수 있다.
} // contextLoads
// ================================================
// JUnit4 버전으로 이름 짓기
// ================================================
@Test
@DisplayName("testDependencyInjection")
@Order(2)
@Timeout(value=1000, unit = TimeUnit.MILLISECONDS)
void testDependencyInjection() {
log.trace("testDependencyInjection() invoked.");
Objects.requireNonNull(this.hotel);
log.info("\t + this.hotel : {}", this.hotel);
// + this.hotel : Hotel(chef=Chef()) ( 호텔 객체가 들어왔음을 알 수 있다. )
// + 호텔 객체 빈 안에도 세프 객체 빈이 필드로 주입된 것을 알 수 있다.
} // testDependencyInjection
// ================================================
} // end class
[ 2. Spring - 의존성 주입 (DI)할 수 있는 어노테이션 종류 ] (****)
[ + 코드 보기 ]
// ================================================
// 의존성 주입(DI) 어노테이션 종류
// ================================================
// @Setter가 가장 추천되는 방식이다. - 세터 메소드를 통해 주입된다. (****)
// @Setter(onMethod_ = @Resource)
// @Setter(onMethod_ = @Inject)
// @Setter(onMethod_ = @Autowired)
// @Resource
// @Inject
@Autowired
private Hotel hotel;
[ 3. Spring - @Setter(onMethod_ = {@Autowired}) ] (**)
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 108일차 - Spring ( MyBatis와 연동 ) (****) (0) | 2022.08.01 |
---|---|
KH 107일차 - Spring ( 설정 / 히카리CP ) (****) (0) | 2022.07.29 |
KH 105일차 - Spring 설치 및 프로젝트 생성 (*****) (0) | 2022.07.27 |
KH 104일차 - mybatis ( 동적 SQL 처리 ) / 쿼츠 (quartz) - 스케줄링 (*****) (0) | 2022.07.26 |
KH 103일차 - myBatis마이바틱스 3 ( 검색조건 설정 / 히카리CP ) (*****) (0) | 2022.07.25 |