Spring Framework ふりかえりと4.3新機能

Preview:

Citation preview

Spring Frameworkふりかえりと4.3新機能木村 俊介 @kimullaa

1

自己紹介

名前:木村俊介(きむらしゅんすけ)

仕事: SI企業の技術部隊@2013

フレームワーク整備と展開、PJ支援

2年前までは Struts + EJB + iBatis ベースの自社FW

現在は Spring + MyBatis を社内に推進、展開

Spring歴: 2年くらい

2

今日のテーマ

基礎をふりかえりながら、Spring Framework 4.3 の新機能をご紹介

『Modern Java Component Design with Spring Framework 4.3』- モダンなSpringの使い方と新機能の説明- スライド- 動画

『Spring MVC 4 Web Apps』- WEB機能(Spring MVC)に絞った新機能の説明- スライド- 動画まだ上がってません

Juergen Hoeller

Rossen Stoyanchev

3

既に話しつくされたネタ感

@Shimizuさんの日本語解説ブログ

http://qiita.com/kazuki43zoo/items/172d132ff8f4ba098888#core-

container-improvements

JSUG勉強会 2016年その4 Spring I/O報告会池谷さんの発表

http://ikeyat.github.io/slides-

publish/slides/201606XX_SpringIO2016Summary/#1

JJUG CCC 2016 Spring @makingさんの発表

http://sssslide.com/www.slideshare.net/makingx/jjugccc-cccgh5-whats-

new-in-spring-framework-43-boot-14-pivotals-cloud-native-approach

Spring Framework リファレンス

http://docs.spring.io/spring/docs/current/spring-framework-

reference/html/new-in-4.3.html

4

でもやります

5

知ってる人は知っている

6

知らない人は覚えてね

7

Spring Framework ふりかえり

8

DIコンテナ

Dependency Injection

Beanの登録

- Java Config- アノテーションベース- XMLベース

Bean BeanBean

Bean Bean

lookup

依存性の解決 メリット:テスタビリティ向上、ライフサイクル管理

9

Aspect Oriented Programming

AOP

AOP

クラスA クラスB

横断的関心事の分離メリット:コード量削減、見通しのよいコード

ログ出力、Tx管理

10

で、こうなる

11

Java Config + アノテーションベース

@Configuration // Java Configの宣言@Profile(“standalone”) // standaloneプロファイル時に有効になる@EnableTransactionManagement // SpringによるTx管理を有効化@ComponentScan(“com.example”) // スキャン&Bean登録

public class AppConfig {

@Bean // Bean定義

public FooService fooService() {// CGLibでUtilityのインスタンスは1度しか生成されない

return new FooServiceImpl(utility());

} @Bean // Bean定義

public Utility utility() {return new Utility();}

}

~4.2

12

@Configuration

public class AppConfig implements FooAppConfig {

…// デフォルトメソッドのBean定義が有効になる

}

public interface FooAppConfig {

@Bean

default FooService fooService() {

return new FooServiceImpl();

}

}

~4.2

13

Java Config & Java8

@Component class

@Service // ComponentScan時にBean登録される@Lazy // Lazy-load(利用時にインスタンス化)

public class FooServiceImpl implements FooService {

private final FooRepository fooRepository;

@Autowired // コンストラクタインジェクション

public FooServiceImpl(FooRepository fooRepository) {

this. fooRepository = fooRepository;

}

@Transactional // AOPでトランザクション管理

public void update() {

}

~4.2

14

Lazy Injection Points

@Bean @Lazy

public FooRepository fooRepository () {

return new FooRepositoryImpl();

}

@Service

public class FooServiceImpl implements FooService {

private final FooRepository fooRepository ;

@Autowired // 依存先のBeanに関係なく@Lazyを有効化できるpublic FooServiceImpl(@Lazy FooRepository fooRepository ) {

this. fooRepository = fooRepository ;

}

}

~4.2

15

合成アノテーション

@Service

@Scope(“session”)

@Primary

@Transactional(rollbackFor = Exception.class, timeout = 30)

public @interface MyCustomService {}

@MyCustomService

public class FooServiceImpl implements FooService {

}

アノテーションを組み合わせられる

~4.2

16

合成アノテーション属性の上書き

@Service

@Scope(“session”)

@Primary

@Transactional(rollbackFor = Exception.class, timeout = 30)

public @interface MyCustomService {

@AliasFor(annotation = Transactional.class, attribute = “readOnly”)

boolean readOnly() default false;

}

@MyCustomService(readOnly=false)

public class FooServiceImpl implements FooService { … }

上書きしたい属性だけ公開できる

~4.2

17

Spring Framework 4.3

18

Spring Framework 4.3

4系のラストリリース(リリース済み)

2019年までサポート

SpringBoot 1.4 のデフォルト

『SpringOne Platform 2016 keynote』より引用

19

Spring Framework 4.3 改善点

Core Container Improvements

Web Improvements

Data Access Improvements

Caching Improvements

JMS Improvements

WebSocket Messaging Improvements

Testing Improvements

今日話すことはこの中の一部

20

Core Container Improvements

21

1. 暗黙的なコンストラクタインジェクション

@RestController

public class Foo {

private final HogeService hogeService;

private final FugaService fugaService;

// @Autowired

public Foo(HogeService hogeService, FugaService fugaService) {

this.hogeService = hogeService;

this.fugaService = fugaService;

}

4.3

コンストラクタが1つなら省略可能

22

2. Java Config クラスでコンストラクタインジェクション

@Configuration

public class AppConfig {

private final Utility utility;

// @Autowiredが書けるようになった(けど省略可能)

public AppConfig(Utility utility) {

this.utility = utility;

}

@Bean

public FooService fooService() {

return new FooServiceImpl(this.utility);

}

}

4.3

23

3. InjectionPoint like CDI

『http://sssslide.com/www.slideshare.net/makingx/jjugccc-cccgh5-whats-new-in-spring-framework-43-boot-14-pivotals-cloud-native-approach』より引用

4.3

4.3

24

活用例. Loggerの生成

public class HelloController {

@Autowired

private Logger logger; //= LoggerFactory.getLogger(HelloController.class)

public void log(){ // … com.example.controllers.HelloController : hello と表示される

logger.info(“hello”);

}

}

@Configuration

public class AppConfig {

@Bean @Scope(value="prototype“, proxyMode = ScopedProxyMode.NO)

Logger getLogger(InjectionPoint ip ) {

return LoggerFactory.getLogger(

ip.getMember().getDeclaringClass().getName()); }

}

4.3

proxyModeがNOなので、自身のスコープよりも広いBeanにインジェクトされると、依存先のスコープになる(CDIの@Dependentみたいなスコープ)

25

@RestController

@Slf4j

public class HelloController {

// Logger log = LoggerFactory.getLogger(HelloController.class);

public void log(){ // … com.example.controllers.HelloController : hello と表示される

log.info(“hello”);

}

}

4.3

コンパイル時に暗黙的に生成される

ただ、lombokはもっとすごい

詳細は TERASOLUNA Server Framework を参照

http://terasolunaorg.github.io/guideline/5.2.0.RELEASE/ja/Appendix/Lombok

.html#lombokhowtouselogger

26

4. Generics-based Injection

@Service

public class HogeServiceImpl implements HogeService {

@Resource(name = “listFoo”) private List<Foo> listFoo;

@Resource(name = “listBar”) private List<Bar> listBar;

}

@Configuration

public class AppConfig {

@Bean(name = “listFoo”)

public List<Foo> fooList(){…}

@Bean(name = “listBar”)

public List<Bar> fooList(){…}

}

型ではなく名前で解決@Autowired ではなく @Resource

http://docs.spring.io/spring/docs/4.2.7.RELEASE/spring-framework-reference/htmlsingle/#beans-

autowired-annotation-qualifiers

~4.2

27

4. Generics-based Injection

@Service

public class HogeServiceImpl implements HogeService {

@Autowired List<Foo> listFoo;

@Autowired List<Bar> listBar;

}

@Configuration

public class AppConfig {

@Bean

public List<Foo> fooList(){…}

@Bean

public List<Bar> barList(){…}

}

4.3

型で解決

28

Web Improvements

29

@GetMapping

@PostMapping

@PutMapping

@DeleteMapping

@PatchMapping

@OptionsMapping

@HeadMapping

1. @RequestMappingの合成アノテーション

理由はあとで

30

@GetMappingの例

@RequestMapping(value = “hello” , method = RequestMethod.GET)

public String hello(){ … }

@GetMapping(value = “hello”)

public String hello(){ … }

4.3

可読性があがったタイプ数が減った

~4.2

31

2. HEAD, OPTIONS の自動サポート

$ curl -i -X OPTIONS http://localhost:8080/hello

HTTP/1.1 200

X-Application-Context: application

Allow: GET,HEAD

Content-Length: 0

Date: Sun, 28 Aug 2016 07:32:23 GMT

$ curl -i --head http://localhost:8080/hello

HTTP/1.1 200

X-Application-Context: application

Content-Type: text/plain;charset=UTF-8

Content-Length: 4

Date: Sun, 28 Aug 2016 07:40:25 GMT

Allowヘッダに対応可能なHTTPメソッドが列挙される。Controllerのメソッドは実行されない。

GETメソッドと同じ。ただしレスポンスボディは空Controllerのメソッドが実行される。

GET付与でHEADとOPTIONSが自動サポート定義方法は@RequestMappingでも@GetMappingでもok

32

3. Webスコープに関する@Scopeの合成アノテーション

@RequestScope

@SessionScope

@ApplicationScope

スコープ 内容

prototype Bean参照ごとに毎回生成

request HTTPのリクエストごとに生成

session ユーザセッションごとに生成

singleton ApplicationContextごとに生成

application ServletContextごとに生成広い

狭い

33

@RequestScope の例

@Component

@Scope(scopeName = “request”, proxyMode = TARGET_CLASS)

public class Foo { … }

@Component

@RequestScope

public class Foo { … }

4.3

可読性があがったタイプ数が減った

~4.2

34

他のスコープを作ってみる

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Scope("prototype")

public @interface PrototypeScope {

@AliasFor(annotation = Scope.class)

ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

@Component

@PrototypeScope

public class Foo { … }

重要なのはここだけ合成アノテーションは簡単

35

4. @RestControllerAdvice

@ControllerAdvice

public class GlobalHandler {

@ExceptionHandler(Exception.class)

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

@ResponseBody

public Foo handle(){…}

@RestControllerAdvice

public class GlobalHandler {

@ExceptionHandler(Exception.class)

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// @ResponseBodyが不要

public Foo handle(){…}

4.3@ControllerAdvice + @ResponseBody

~4.2

36

5. @RequestAttribute

@RequestMapping(value = “foo”, method = RequestMethod.GET)

public String foo(HttpServletRequest request) {

String param1 = (String) request.getAttribute(“param1”);

… }

@RequestMapping(value = “foo”, method = RequestMethod.GET)

public String foo(@RequestAttribute(“param1”) String param1){…}

4.3

Servlet API に依存せずに取得できる

~4.2

37

6. @SessionAttribute

@RequestMapping(value = “foo”, method = RequestMethod.GET)

public String foo(HttpSession httpSession) {

String param1 = (String) httpSession.getAttribute(“param1”);

… }

@RequestMapping(value = “foo”, method = RequestMethod.GET)

public String foo(@SessionAttribute(“param1”) String param1){…}

4.3

Servlet API に依存せずに取得できる

~4.2

38

7. @ModelAttribute(binding = false)

@ModelAttribute

public Book setUpBook() {// おすすめの本の取得

return new Book(“spring”);

}

@PostMapping(“purchase”)

public void purchase (BookForm form,

@ModelAttribute(binding = false) Book book) {

}

4.3

リクエストパラメータのバインドを抑制する

リクエストパラメータがバインドされる(titleはjavaee)

リクエストパラメータをバインドせずにModelの値を取得する(titleはspring)

curl –X POST localhost:8080/purchase?title=javaee

Bookクラス、BookFormクラスはtitleフィールドを持つとする

39

おわりに

40

詳細はここ

@Shimizuさんの日本語解説ブログ

http://qiita.com/kazuki43zoo/items/172d132ff8f4ba098888#core-

container-improvements

JSUG勉強会 2016年その4 Spring I/O報告会池谷さんの発表

http://ikeyat.github.io/slides-

publish/slides/201606XX_SpringIO2016Summary/#1

JJUG CCC 2016 Spring @makingさんの発表

http://sssslide.com/www.slideshare.net/makingx/jjugccc-cccgh5-whats-

new-in-spring-framework-43-boot-14-pivotals-cloud-native-approach

Spring Framework リファレンス

http://docs.spring.io/spring/docs/current/spring-framework-

reference/html/new-in-4.3.html

41

42

Javaは、Oracle Corporation及びその子会社、関連会社の米国及びその他の国における登録商標です。TERASOLUNAはエヌ・ティ・ティ・データにおける登録商標です。その他、記載されている会社名、商品名等は各社の商標または登録商標である場合があります。

Recommended