본문 바로가기
FrameWork & Runtime/Spring

Spring Bean & Dependency Injection(DI)

by jaeaemin 2022. 3. 1.

Spring Boot 계층형 아키텍처 패턴 

앞서 Spring Boot의 계층형 아키텍처 패턴에 대해서 다시 짚고 넘어가자 ! 

 

 

 

https://www.codepresso.kr/

위의 그림은 아래와 같이 정리할 수 있는데

 

1. 표현 계층 [@Controller]               : Clinet의 요청을 받아 app계층에 처리를 위임하고, 최종 결과를 Client에게 전달함

2. 애플리케이션 계층 [@Service]       : 애플리케이션을 위한 다양한 비지니스 로직들이 위치하고, 데이터가 처리된다.

3. 데이터접근 계층 [@Repository]     : DB에 접근하여 CURD를 수행하는 역할 

 

 

Spring Service 계층은 시스템의 핵심 비지니스 로직을 구현하는 계층으로 , 데이터를 저장하고, 연산 처리, 사용자에게 표시할 내용 선택 등 실제 서비스의 수행이 이루어지는 부분이다.

이 때 Service 계층은 View & Database의 종류와 상관없이 독립적인 계층으로 , 두 설정으로 인해 영향이 생기지 않도록 설계해야 한다.

 

 

 

Service의 구현 

  1. 클래스에 @Service Annotation을 매핑시킴
  2. 파라미터로 전달 된 데이터에 대해서 검증 작업을 수행함
  3. Repository 계층을 활용하여 DB에 접근함 
    1. Service 계층의 단일 메소드가 Transaction의 단위로 작용함 
  4. 애플리케이션의 세부 영역별로 클래스를 생성하여 구현하는게 바람직함
  5. 인터페이스의 사용이 권장되나, 다형성을 활용한 기능 확장의 요구사항이 없는 경우 사용하지 않는 경우도 있음 

 

https://www.codepresso.kr/

위의 그림과 같이 애플리케이션의 세부 영역별로 클래스를 생성하여 구현한다.

( Service 계층 : 다양한 @Service Annotaion이 사용된 클래스들의 묶음 ) 

 

 

 

#### Service 계층과 Controller의 연결 ####

 

[1]핵심 비지니스를 담당할 Service 계층의 클래스를 생성함 ( in service 패키지 )

@Service
public calss PostService {
	public void getPost(Integer id) {
    	System.out.println("비지니스 로직 수행 중 : id 데이터 찾는중 " + id);
        System.out.println("DB에 접근하고 data 검증 중");
    }
}

 

 

 

[2] PostController에서 PostService 계층을 사용하도록 객체를 선언

그 후 객체를 사용함

[ new 키워드를 통해 다른 객체를 사용함 = DI ]

@RestController
@RequestMapping(value="/post")
public class PostController {
    public PostService postService = new PostService();
    
    @GetMapping
    public PostDto getPost(@RequestParam Integer id) {
    	PostDto reuslt = postService.getPost(id); // Service계층 사용
        return result 
    }
}

 

 

 

 

 

 

Spring Bean & 의존성 주입 ( Dependcy Injection ) 

 

의존성(Dependecy)이란? 

     하나의 모듈(클래스, 패키지 등)이 다른 모듈을 사용하는 것을 말한다. -new-

 

 

# PostController 클래스는 PostService에 의존(의존성이 있다)한다. ( PostService가 없으면 동작 못함 )

Class PostControl <===> Class PostService 
PostService service = new PostService();

method getPost() {
          service.getPostById() 
}

←  →

←  →

method getPostById() {
             System.out.println( "id 출력" );
}
Controller 클래스에서 PostService 객체를 생성해서 객체의 method에 접근하는 상황 
( 코드 상에 객체를 생성하여 compile-time 의존성이 생성 )

 

객체의 활용을 위한 의존성 

  • 일반적으로 다른 객체의 기능을 사용하기 위해서는 멤버 변수에 new로 사용할 기능의 객체를 생성하고 참조한다.
  • 생성한 객체의 메서드를 호출하여, 다른 객체의 기능을 사용한다.
  • 어떤 객체를 생성하여 사용할 것인지 코드 상에 명시한다. 
    • Compile-time 의존성이 생성 됨 ( 코드에 위치하니까 ! )

 

 

 

 

의존성 주입(Dependecy Injection)이란? 

     객체 생성을 외부에서 대신 수행하는 것을 말한다.    ==>    new (X)

 

  • 활용할 객체에 대한 의존성(참조)설정을 외부에서 대신 해준다.
  • 활용할 클래스(인터페이스) 타입의 멤버 변수만 선언 후 생성자를 구현한다.
  • new 키워드로 객체 생성을 직접 하지 않는다 !! '

 

####의존성 주입을 통한 PostService 객체 생성 ###### 

@RestController 
@RequestMapping(value = "/post")
public class PostController {
	// 빈 클래스 타입의 멤버 변수만 선언 
    public PostService postService;
    
    // 생성자에서 객체에 대한 초기화 수행 ?
    public PostController(Post Service postService) {
    	this.postServilce = postService;
    }
    
    @GetMapping
    public PostDto getPost(@RequestParam Integer id) {
    	PostDto res = postService.getPost(id);
        return res;
    }
}

위의 클래스에서는 클래스(인터페이스) 타입의 멤버 변수만 선언하고 객체를 할당해 주지 않았다. (참조만 가능하게)

하지만 생성자에서 멤버 변수를 인자로 받아서 할당해준다. 

PostController 객체의 postService 변수는 누가 할당하는 것인가 ?  외부에서 런타임 내 생성자를 사용하는 곳에서 결정한다 ! 

 

특정 클래스가 사용하는 다른 객체를 코드상에서 명시하는 것이 아니라, 런타임 내 외부에서 결정해서 생성된 객체를 생성자로 주입시킨다.

즉 어떤 객체를 사용할 지 외부에서 결정함 !! 

 

 

 

Spring Framework가 객체를 생성하고 관리하는 Cycle의 예시

  1. Spring Framework가 소스코드를 스캔 
  2. 어노테이션을 만나면 객체를 생성함
  3. 만들 객체[1]의 생성자에서 다른 객체[2]가 필요하면 그 객체를 찾으러 떠난다.
  4. 객체[2]를 찾으러 갔는데 @Service라는 어노테이션이 있을 때, 객체를 생성해서 프레임워크가 관리한다.
  5. 객체[2]를 생성해서 Spring Framework가 가지고 있고 관리한다.
  6. 객체[2]가 있으니까 아까 못한 객체[1]의 생성자를 구동시키고 객체[1]을 만들자
  7. 객체[1]은 객체[2]에 의존성을 가지게 되었음 !

 

 

 

 


Spring Ioc 컨테이너 

 - Sping Framework에서 객체의 생성과 관리의 역할을 하는 컴포넌트

 - 사용자가 framework를 사용하는 것이 아닌, framework가 사용자의 코드를 사용하면서 구동

 

Spring Bean

 - Spring Ioc 컨테이너에 의해서 생성되어 관리되는 Java 객체

 - 즉 Ioc 컨테이너가 만들고 관리하는 Java 객체


 

 

의존성 주입의 단계 

 

[1] 객체 생성 방법 

 

1. Spring에 의해 Bean 객체가 생성되게끔 Annotation을 설정함

              (1-1) RestController , @Service 등의 어노테이션의 클래스들을 컴포넌트 스캔 단게에서 객체로 생성해줌

2. 사용할 객체를 멤버 변수와 생성자에 추가한다.

3. 객체를 사용한다.

( 객체를 멤버 변수로 선언하고 , 생성자에 추가하기만 하면 Spring Framework에 의해 생성&관리된다. ) 

 

 

 

[2] 객체 생성 방법 - 2

 

@Configuration 

  • Java 클래스에 @Configuration Annotation을 사용할 수 있다.
  • Annotation에 해당하는 클래스는 Spring Framework에 의해 설정 정보를 위한 클래스로 활용된다.

 

@Bean Annotaion 

  • @Configuration 클래스 내에 @Bean을 사용한 메소드로 Bean을 생성하는 것이 가능하다.
  • Bean으로 등록할 객체를 생성 후 Return하게 된다.
  • Bean이란 리턴 객체가 Spring에 의해서 생성되고 관리되는 Java 객체를 의미함 
  • Bean들은 의존성을 가지고 서로 상호작용이 가능함

 

#### Configuration을 통해 미리 Bean 객체를 설정 #####

@Configuration
public class AppConfig {

   @Bean
    public PostService postServie() {
    	return new PostService();
    }
}

 

 

 

#### Configuration을 통해서 생성되어 프레임 워크에서 관리되고 있는 Bean 객체 사용 #####

@RestController 
@RequestMapping(value = "/post")
public class PostController {
    // 클래스 타입의 멤버 변수만 선언 
    public PostService postService;
    
    // Spring Framework의 Bean으로 등록되어 관리되고 있어서 사용이 가능함
    public PostController(Post Service postService) {
    	this.postServilce = postService;
    }

 

 

 

 

 

 

<정리> Spring Framework가 조건에 대해 객체를 생성하는 방법 

1.  클래스 상단의 Annotation 정보를 활용하여 객체를 생성함 ( @Controller, @RestController, @Service 등 )

2. @Configuration 클래스의 @Bean을 통해서 객체를 생성하고 프레임워크를 통해 관리하고 있는다.

3. XML 설정

[ 객체로 생성할 대상을 검색하는 과정을 Component Scan 이라고 한다. ]

 

반응형

'FrameWork & Runtime > Spring' 카테고리의 다른 글

Spring Session & Cookie  (0) 2022.03.09
MyBatis  (0) 2022.03.07
Spring의 Request & Response  (0) 2022.03.01
Spring 서비스 계층  (0) 2022.02.28
<코드 프레소 웹 개발 트랙> Spring Boot 웹 개발 초급 [1]  (0) 2022.02.22