spring boot di

21
Spring Boot 를 를를를 DI 를를 2015.11.01 를를를 : Hong Hyo Sang

Upload: -

Post on 14-Jan-2017

545 views

Category:

Education


0 download

TRANSCRIPT

Page 1: Spring boot DI

Spring Boot 를 이용한 DI 학습

2015.11.01작성자 : Hong Hyo Sang

Page 2: Spring boot DI

Content

1 필요한 Tool

2 Spring 이용한 App

3 Spring Application 추상화

4 Spring DI 적용 ( Auto-wiring )

5 Component Scan 을 사용 하여 자동으로 Bean 등록

6 CommandLineRunner 이용 하기

Page 3: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 3

1. 필요한 Tool

• java - http://www.oracle.com/technetwork/indexes/downloads/index.html - version 1.8.0_65 Java SE

- 환경 설정 : JAVA_HOME , PATH• STS ( Spring Tool Suite )

- http://spring.io/tools/sts - version :

• lombok - https://projectlombok.org - version : 1.16.6 ::

• curl ( 명령 프롬프트에서 http client program ) - http://curl.haxx.se/download.html - version :: Win64 ia64 zip :: http://curl.haxx.se/latest.cgi?curl=win64-ssl-sspi - 환경 설정 : PATH 에 추가

• maven - maven.apache.org/download.cgi - 환경 설정 : MAVEN_HOME , PATH 에 추가

1. 필요한 Tools

Page 4: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 4

• 두 값을 입력 받아서 화면에 출력 한다 .2-1. 요구 사항

2. Spring 이용한 App

1. STS 실행2. File > New > Spring Startup Project 선택

- Name :: SpringDiPrint- Group :: com.iabacus- Artifact :: SpringDiPrint- Version :: 0.0.1-SNAPSHOT- Description :: Spring Boot 를 이용한 두 수 입력 받아서 출력 - Package :: com.iabacus- Maven 으로 설정 함

3. Next 버튼을 클릭 후 나오는 화면에서 아무 것도 선택 하지 않고Finish 버튼을 클릭 한다 .- Spring Boot Starter 만을 이용해서 작업 하므로

4. 생성 후 Package

2-2. Project 생성

그림 1. File > New > Spring Startup Project

Page 5: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 5

…<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.2.7.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent>

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version></properties>

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>…

2-3. pom.xml

2. Spring 이용한 App

Page 6: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 6

…<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.2.7.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent>

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version></properties>

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>…

2-4. pom.xml

2. Spring 이용한 App

Page 7: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 7

2-5. 프로그램 작성

2. Spring 이용한 App

• Package Explorer• ValuePrint Interface 를 만든다 .

• ValuePrintImpl Class 만든다 .

Page 8: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 8

2-5. 프로그램 작성

2. Spring 이용한 App

• SpringDiConfig Class 를 만든다 .

Bean 정의 파일 작성은 Spring 에서 두가지 방법이 존재 한다 .- Xml 정의- Java Config 정의 ( Spring v3.0 부터 도입 )

@Configuration annotation :: Java Config 용 Class 임을 컴파일러에 알린다 .@Bean :: DI 컨테이너가 관리할 Bean 을 생성하는 Method 로 기본적으로 Method 이름이 Bean 이름이 된다 . 기본적으로 Singleton 이 되며 , DI 컨테이너별로 인스턴스 한 개 생성된다 .return new ValuePrintImpl(); :: ValuePrint() 생성자로 생성한 ValuePrint 타입의 ValuePrint 인스턴스를 DI 컨테이너가 Singleton으로 관리 한다 .

Page 9: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 9

2-5. 프로그램 작성 및 설명

2. Spring 이용한 App• SpringDiPrintApplication

Class

@EnableAutoConfiguration :: Spring 의 다양한 설정을 파일 없이 자동으로 수행 된다 .@Import(SpringDiConfig.class) :: Java Config 를 읽어 들이기 위해서 @Configuration annotation 이 붙은 class 를 지정 한다 ,

DI 컨테이너에서 ValuePrint 타입의 인스턴스를 받는다 .

표준 입력 장치로 값을 받는다 .

Page 10: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 10

2-5. 프로그램 작성

2. Spring 이용한 App• SpringDiPrintApplication

Class

try (ConfigurableApplicationContext context = SpringApplication.run(SpringDiPrintApplication.class, args)) {

………

}SpringApplication.run() 으로 Spring Boot Application 을 실행 한다 .ApplicationContext 객체를 반환 받는데 ( DI 컨테이너 본체 ) 이 예제에서는 Close() 로 닫을 수 있는 ConfigurableApplicationContext 를반환 받는다 .Try-with-resource 문 안에 변수를 선언 하여 try 안쪽에서 처리가 끝나면 자동으로 close() 메소드가 호출 되어 DI 컨테이너가 소멸 되고 Application 이 종료 된다 .

자바 7 에서 try-with-resources 라는 특징이 추가되었다 . 이건 문법 차원에서 추가된 건데 , try 에 자원 객체를 전달하면 finally 블록으로 종료 처리를 하지 않아도 try 코드 블록이 끝나면 자동으로 자원을 종료해주는 기능

try (InputStream in = new FileInputStream(inFile);     OutputStream out = new FileOutputStream(outFile)) {    ...} catch(IOException ex) {    ...}// in 과 out 모두 자동으로 종료됨

종료 후 보이는 메시지 ::2015-11-01 05:14:45.627 INFO 44952 --- [ main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3cb1ffe6: startup date [Sun Nov 01 05:14:38 KST 2015]; root of context hierarchy2015-11-01 05:14:45.629 INFO 44952 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown

Page 11: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 11

2-6. 프로그램 실행

2. Spring 이용한 App• Run as > Java Project

2015-11-01 05:14:45.627 INFO 44952 --- [ main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3cb1ffe6: startup date [Sun Nov 01 05:14:38 KST 2015]; root of context hierarchy2015-11-01 05:14:45.629 INFO 44952 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown

Page 12: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 12

3-1. Set, Get 을 쉽게 만들수 있도록 lombok 를 pom.xml 에 추가 .

3. Spring Application 추상화

• lombok 을 사용 하기 위해서 pom.xml 에 다음과 같이 추가 한다 . <dependency>

<groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.4</version> <scope>provided</scope> </dependency> :: Maven Dependenies 에 lombok-1.16.4.jar 가 추가 된 것을 확인 할 수 있다

*** Lombok 은 OpenSource project 로 eclipse 에 설치해서 annotation 등을 이용하여 반복적으로 생성하는 지루한 코드들을 내부적으로 추가 한다 . ***

@Getter, @Setter :: 자동으로 getter, setter 들을 만들어준다 .accesslevel 도 지정가능하고 , override 도 가능하다 .

@Getter(lazy=true) :: thread-safe 한 getCached() 라는 함수를 만들어준다 . 이 함수는 expensive 한 작업에 대해서 cache 를 뜬다 .

@ToString :: field name 을 기준으로 toString 을 자동생성해준다 . 옵션을 통해 super class 의 toString 도 부를지 , fieldname 도 넣어줄지 , exclude 할 field 가 있는지 지정할 수 있다 .

@EqualsAndHashCode :: euqlas 와 hashCode 함수를 만들어준다 .

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor :: 여러가지 종류의 constructor 를 자동으로 만들어주며 , @NotNull option 에 따라 null check 도 해준다 .

@Data :: @Tostring, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor 를 자동으로 생성 함

@Cleanup :: close() 함수를 불러줘야 하는 Stream 류 등의 close 를 보장해준다 .

@Synchronized :: 기본 synchronized 와 비슷하지만 , 다른 lock 을 생성해서 handle 한다 . class 나 this 로 lock 을 거는 것은 외부에서도 할 수 있기 때문에 안전하지 못하다 .

@SneakyThrows

@Log

Page 13: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 13

3. Spring Application 추상화3-2. 표준 입력 장치에서 받는 것을 추상화 한다 .• com.iabacus.domain package 를 생성 한다 .1) domain 객체를 생성 한다 . ( ValueArgumentDomain.-java )

2) ValuePrint 의 인자를 받는 Interface 를 만든다 .

3) 표준입력 장치에서 입력을 받는 class 를 만든다

Page 14: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 14

3. Spring Application 추상화

4) Bean 정의 파일에 추가 한다 .

5) DI 컨테이너에서 ValueArgument 을 가져오도록 SpringDiPrintApplication 의 main 을 수정 한다 .

Page 15: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 15

3. Spring Application 추상화

6) 자바 실행 Run As > Java Application

Page 16: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 16

4. Spring DI 적용 ( Auto-wiring )

2,3 DI 컨테이너에서 Bean 을 가져 오는 방법에 대해서 살펴 보았다 . 만약 프로그램이 커지면 context.getBean() 을 호출 하는 것이 많아 질 것이다 . 지금 부터는 DI 를 이용한 방법으로 현재 프로그램을 변경 한다 .

4-1. Auto-wiring 적용 하기

DI 컨테이너에 Bean 을 Inject 하기 위해서 먼저 Application 의 구현을 처리 할 class 을 만들고 이 class 에 앞에서 만들어 놓았던 ValueArgument, ValuePrint Calss 를 Inject 한다 .

Page 17: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 17

4. Spring DI 적용 ( Auto-wiring )4-2. Bean 추가 하기

Page 18: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 18

4. Spring DI 적용 ( Auto-wiring )4-3. Application 변경

실행을 하면 동일 한 결과를 얻을 것 입니다 .

Page 19: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 19

5. Component scan 을 사용 하여 자동으로 Bean 등록 2,3,4 에서와 같이 Bean 등록을 위해서 java config 을 이용 한다면 많아지는 Bean 에 대해서 관리가 필요 할 것 이다 , 그래서

Spring 에서는 Bean 을 DI 컨테이너에 자동으로 등록 하는 Component Scan 기능을 제공 한다 . @ComponentSacn annotation 을 class 에 붙이면 package 내부의 class 검색 하여 @Component 와 같은 annotation 이

붙은 java class 를 찾아내서 DI 컨테이너에 등록 한다 .

@ComponentSacn 에 대상이되는 annotation 는 @Component, @Controller, @Service, @Repository 가 있다 . 다음과 같이 수정을 하고 실행을 하여도 동일한 결과를 얻는다 .

- SpringDiPrintApplication.javja @EnableAutoConfiguration @ComponentScan public class SpringDiPrintApplication { …. }

- AppRun.java @Component public class AppRun { …. }

- ValueArgumentImpl.java @Component public class ValueArgumentImpl implements ValueArgument { … }

- ValuePrintImpl.java @Component public class ValuePrintImpl implements ValuePrint { …. }

- com.iabcus.config 폴더 삭제

Page 20: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 20

6. CommandLineRunner 이용 DI 컨테이너가 Application class 를 inject 하게 하는 할 수 있는 CommandLineRunner 를 사용 해서 프로그램을 변경 하자

- AppRun.java 삭제 - SpringDiPrintApplication.java 파일 수정

package com.iabacus;

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;

import com.iabacus.domain.ValueArgumentDomain;import com.iabacus.study.ValueArgument;import com.iabacus.study.ValuePrint;

@EnableAutoConfiguration@ComponentScanpublic class SpringDiPrintApplication implements CommandLineRunner {

@Autowired ValueArgument valueArgment;

@Autowired ValuePrint valuePrint;

public static void main(String[] args) { SpringApplication.run(SpringDiPrintApplication.class, args); }

@Override public void run(String... arg0) throws Exception { ValueArgumentDomain valueArgumentDomain = valueArgment.setArgument(System.in); String result = valuePrint.valueSystemPrint(valueArgumentDomain.getA(), valueArgumentDomain.getB()); System.out.println(result); }}

CommandLineRunner interface 를 구현 하는클래스는 Dependency injection 을 할 수 있다 .

run method 를 override 하여서 구현 한다 .

Page 21: Spring boot DI

Copyright©2015 ABACUS, Co. All rights reserved. 21

별첨 : Spring Starter Project Spring Starter Project 로 생성시 @SpringBootApplication annotation 으로 되어 있는데 이것은 다음을 포함 한다 .

- @Configuration, @EnableAutoConfiguration, @ComponentScan

package com.iabacus;

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;

import com.iabacus.domain.ValueArgumentDomain;import com.iabacus.study.ValueArgument;import com.iabacus.study.ValuePrint;

@SpringBootApplication public class SpringDiPrintApplication implements CommandLineRunner {

@Autowired ValueArgument valueArgment;

@Autowired ValuePrint valuePrint;

public static void main(String[] args) { SpringApplication.run(SpringDiPrintApplication.class, args); }

@Override public void run(String... arg0) throws Exception { ValueArgumentDomain valueArgumentDomain = valueArgment.setArgument(System.in); String result = valuePrint.valueSystemPrint(valueArgumentDomain.getA(), valueArgumentDomain.getB()); System.out.println(result); }}