일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- flink watermarks
- 가변성
- processing time
- Heuristic Watermarks
- MapReduce
- Heuristic Watermark
- coroutines
- event time
- lambda
- 불공변
- Coroutine
- covariant
- Perfect Watermark
- Stream
- watermark
- HDFS
- flink
- watermarks
- contravariant
- apache flink
- Generics
- flink watermark
- Hadoop
- Perfect Watermarks
- 공변
- java
- Generic
- kotlin
- ingestion time
- Today
- Total
mm Home
Spring 5 features 본문
Spring 5 features
- 리액티브 프로그래밍 모델
- 어노테이션 기반 MVC + 함수형 MVC 같이 지원. 기존의 어노테이션 기반을 사용할 수도 있지만, 함수형으로 MVC 설정을 할 수도 있다.
- 간단하게 설정을 어떻게 하는지 방법만 봐보자. 다음 글에서 web-flux에 대하여 자세히 설명하겠다.
- 라우터를 통해 request를 적절한 핸들러에 라우팅한다.
- 핸들러가 컨트롤러가 된다.
- 아래와 RouterFunction을 설정해서 스프링의 Bean으로 생성한다면 DispatcherHandler 에서 관련 빈들을 다 불러들여서 해당 Handler로 라우팅한다.
- WebClient 클래스 추가
- RestTemplate을 대체할 비동기 논블록킹 HTTP 클라이언트
람다를 통한 스프링 빈 등록 가능
- 람다를 통해 단일 메서드를 가지는 Supplier 타입의 빈 등록이 가능하다.
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(Book.class, () -> new
Book(context.getBean(Author.class))
);
- spring-webflux 통합 테스트 지원
- WebTestClient 가 서버를 띄우지 않고 WebFlux 서버 구조에 바로 바인딩할 수 있다.
RouterFunction bookRouter = RouterFunctions.route(
RequestPredicates.GET("/books"),
request -> ServerResponse.ok().build()
);
WebTestClient
.bindToRouterFunction(bookRouter)
.build().get().uri("/books")
.exchange()
.expectStatus().isOk()
.expectBody().isEmpty();
- Junit 5
- 새로운 어노테이션
- @TestFactory – denotes a method that is a test factory for dynamic tests
- @DisplayName – defines custom display name for a test class or a test method
- @Nested – denotes that the annotated class is a nested, non-static test class
- @Tag – declares tags for filtering tests
- @ExtendWith – it is used to register custom extensions
- @BeforeEach – denotes that the annotated method will be executed before each test method (previously @Before)
- @AfterEach – denotes that the annotated method will be executed after each test method (previously @After)
- @BeforeAll – denotes that the annotated method will be executed before all test methods in the current class (previously @BeforeClass)
- @AfterAll – denotes that the annotated method will be executed after all test methods in the current class (previously @AfterClass)
- @Disable – it is used to disable a test class or method (previously @Ignore)
- 예외 처리 테스트 가능
- 동적 테스트
- 테스트 런타임시 테스트에 대한 정의를 하고 실행할 수 있게끔 DynamicTest를 지원한다.
- 새로운 어노테이션
각 feature 들을 자세히 살펴보질 않아서... 대략적으로 적어봤다. 관심이갔던 web-flux 부분은 좀 더 살펴보고 있는데, 다음에 더 자세히 적어보겠다.
간략하게 정리를 하면.
Spring 5 - web-flux 예제
reactive web → web flux란 이름으로 변경됨.
Reactive Programming을 지원하기 위한 스프링의 새로운 프로젝트.
참고로 spring boot 2.0(아직 M6) 부터 default 컨테이너를 netty 이용함.
- netty는 비동기 블록킹 개발에 가장 많이 사용됨.
- tomcat 을 기본으로 하지 않는다. Servlet 기술에 의존하지 않도록 web flux가 개발된 것.
Spring 5에 들어서 MVC 를 위한 web 프로젝트로 2개 중 1개를 선택해야 함.
- web-mvc : 기존 JAVA EE의 Servlet 기반. MVC의 주체 DispatcherServlet
- web-flux : reactive web. DispatcherServlet → DispatcherHandler 로 변경.
Mono & Flux 클래스 추가
- Publisher 클래스
- Mono : 하나의 요소를 다룰 때
- Flux : 하나 이상의 요소를 다룰 때
- value를 지니고 있는 컨테이너 클래스.
- publisher인데 Mono와 Flux로 객체 생성(데이터 stream 생성)은 어떻게 해야하나?
- Optional과 동일하게 JPA로 구성시 자동으로 Flux나 Mono로 감쌀 수 있다. (Flux로 감싸는 경우 Flux<List<Object>> 가 아니라 Flux<Object> 이다.)
- 아니면 just라는 메소드를 통해 객체를 생성할 수 있다.
Mono & Flux 는 모나드 클래스이면서 Publisher 이다.
값이 컨테이너에 담겨있기 때문에 값을 꺼내는 함수를 써야한다. 그런데 Publisher이기 때문에 Subscriber에 의해 구독되기 전에 값을 꺼내지 못한다.
Spring web-flux 에서 Mono나 Flux를 리턴해주면 저절로 subscribe 해준다.
비동기 개발이기 때문에 start와 end 로그가 찍히고 실제 로직 동작이 이루어지는 것을 확인할 수 있다.
subscribe() 메소드를 호출하기 전까지 동작을 하지 않는다고 보면 될것이다.
userFlux라는 객체가 구독될때까지 지연평가되는 것이다.
서비스 로직에서 직접 값을 꺼내야될 때는 .subscribe() 를 호출하면 된다. 빈 파라미터면 리턴값은 disposable.
궁금해서 코드를 쭉 따라가본, 간략한 web-flux 의 Mono, Flux 처리 프로세스
- 기본적인 Dispatch 처리 과정은 spring mvc와 비슷한것 같다.
- DispatcherHandler 이 초기화될때 mvc의 전략 빈들을 주입. (아래의 3개 인터페이스는 스프링 4버전대의 인터페이스와 다르다)
- 디폴트 빈들은 @EnableWebFlux 을 사용하면서 객체 생성이 될 것이다.
- 디폴트 빈에 대한 설정은 WebFluxConfigurationSupport 클래스에서 확인할 수 있다.
- DispatcherHandler가 초기화할때 스프링 컨텍스트 내에 있는 빈들에서 해당 인터페이스 빈들을 불러들여 주입시킨다.
- HandlerMapping : Request와 핸들러(메소드) 객체 매핑을 정의하는 인터페이스
- HandlerAdapter : HandlerMapping이 핸들러(메소드)를 찾아주면, HandlerAdpter가 해당 컨트롤러의 핸들러에 전달하기 위한 Adapter 인터페이스
- ResultHandler : HandlerAdapter 에 의해 반환된 값을 처리하기 위한 인터페이스
- netty 동작 기반은 더 살펴볼 예정.
- NioEventLoop
- 어쨋든 request가 오면 DispatcherHandler의 handle(ServerWebExchange exchange) 메소드를 호출한다. (ServerWebExchange는 HTTP 요청/응답에 대한 인터페이스)
- 여기서 체이닝걸려있는 함수를 거치며 결과를 반환하게 되는데...
- 적절한 핸들러를 찾는다.
- 핸들러를 실행한다.
- 주입된 핸들러 아답터들을 순회하며 적절한 아답터를 찾는다. (supports)
- 아답터를 통해서 핸들러 handle
- 결과를 반환한다.
- 주입된 resultHandler들 중 적절한 핸들러를 찾음.
- 핸들러가 handleResult 한다. (결과를 뽑음)
- @ResponseBody의 핸들러 중 Mono로 반환되는 경우를 예로 보면, ResponseBodyResultHandler 라는 클래스가 handleResult 메소드를 호출하여 결과값을 생성하여 write 한다.
시간이 날때 더 자세히 찾아서 정리해보아야겠다.
참고 :
https://www.ibm.com/developerworks/library/j-whats-new-in-spring-framework-5-theedom/
http://www.baeldung.com/junit-5
'개발 > Spring' 카테고리의 다른 글
Spring MVC - DispatcherServlet 동작 원리 (2) | 2017.09.26 |
---|---|
ComponentScan 동작 원리 (1) | 2017.09.14 |