Slide 1

Slide 1 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナから紐解く 本当のSpring⼊⾨ (株)カサレアル 多⽥真敏 2019年8⽉28⽇ JSUG勉強会 1

Slide 2

Slide 2 text

(C) CASAREAL, Inc. All rights reserved. #jsug このセッションについて ▸ Springの基礎となる「コンテナ」「DI」に
 ついて、基礎から分かりやすく解説します ▸ 基本的に初⼼者向けですが、
 Springを利⽤している全ての⽅が対象です 2

Slide 3

Slide 3 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⾃⼰紹介 ▸ 多⽥真敏(@suke_masa) ▸ 研修トレーナー@カサレアル ▸ Spring / Java EE / Microservices
 / Cloud Foundry ▸ Pivotal認定講師 ▸ ⽇本Springユーザ会スタッフ 3

Slide 4

Slide 4 text

(C) CASAREAL, Inc. All rights reserved. #jsug お願い:⾳にご注意ください! ▸ メモを取る際のキータッチは優しくお願いします。 ▸ スライドは後ほどWebにアップしますので、
 スライドの写真撮影はなるべくしないでください。 ▸ どうしても撮影されたい場合は、
 Microsoft Pixなど⾳のしないカメラアプリを
 ご利⽤ください。 4

Slide 5

Slide 5 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 5

Slide 6

Slide 6 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 6

Slide 7

Slide 7 text

(C) CASAREAL, Inc. All rights reserved. #jsug Springの誕⽣ ▸ 2002年、Rod Johnson⽒が⾃著の サンプルプログラムとして作成 ▸ 重くて複雑だった当時のJ2EE・EJBに
 対するアンチテーゼだった ▸ Johnson⽒が会社を⽴ち上げたり、
 買収されたり紆余曲折あって、
 現在はPivotal社が中⼼に開発 7

Slide 8

Slide 8 text

(C) CASAREAL, Inc. All rights reserved. #jsug Springの歴史 8 年 バージョン できごと 2002 ??? Johnson⽒が本を執筆 2004 Spring 1.x OSS化、XML設定ファイル 2006 Spring 2.x アノテーション対応、MVC誕⽣ 2009 Spring 3.x Java Config、REST対応 2014 Spring 4.x Java 8対応、Spring Boot誕⽣ 2017 Spring 5.x Java 8ベース(9以上も対応)、リアクティブ

Slide 9

Slide 9 text

(C) CASAREAL, Inc. All rights reserved. #jsug 数々のSpringプロダクト 9 プロダクト 説明 Spring MVC Webフレームワーク Spring Data データアクセス Spring Security 認証・認可 Spring Batch バッチ処理フレームワーク Spring Boot 設定の簡素化 Spring Cloud マイクロサービス開発

Slide 10

Slide 10 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 10

Slide 11

Slide 11 text

(C) CASAREAL, Inc. All rights reserved. #jsug Springはコンテナを持っている ▸ コンテナ=インスタンスの⼊れ物 ▸ Bean=コンテナで管理されたインスタンス 11 コンテナ Bean Bean Bean Bean Bean ※「インスタンス」とは、
  もちろんJavaのインスタンスの
  ことです 必要に応じて
 取り出して使う

Slide 12

Slide 12 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナは全Springプロダクトのベース ▸ 例:Spring MVCはDispatcherServlet内に
   コンテナを持っている 12 DispatcherServlet コンテナ Bean Bean Bean 12 必要に応じて
 取り出して使う

Slide 13

Slide 13 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナの機能(詳細は後述) ① Dependency Injection ② スコープの管理 ③ プロキシの作成 13

Slide 14

Slide 14 text

(C) CASAREAL, Inc. All rights reserved. #jsug Beanを定義する⽅法 ① コンポーネントスキャン ② Java Config ③ 関数型Bean定義 (今回は割愛) ④ XML (今回は割愛) 14 これらの⽅法は、全て併⽤可能!

Slide 15

Slide 15 text

(C) CASAREAL, Inc. All rights reserved. #jsug Bean定義⽅法① コンポーネントスキャン ▸ コンポーネントスキャン
 =指定されたパッケージから@Componentが
  付いたクラスを探す ▸ ⾒つけたらインスタンス化→コンテナに保存 15

Slide 16

Slide 16 text

(C) CASAREAL, Inc. All rights reserved. #jsug ▸ 右記のアノテーションを
 クラスに付けると、
 @Componentを付けた
 ことと同じになる ▸ クラスの役割に応じて
 変える 16 @Repository @Service @Controller @RestController @Configuration @ControllerAdvice @RestControllerAdvice ɾɾɾ Bean定義⽅法① コンポーネントスキャン ※これらのアノテーションのソースコードを読むと、
  @Componentが付いていることが分かります

Slide 17

Slide 17 text

(C) CASAREAL, Inc. All rights reserved. #jsug Bean定義⽅法① コンポーネントスキャン 17 package com.example; @Component public class Hoge { ... } @Configuration @ComponentScan(basePackages = "com.example") public class AppConfig {} ▸ Beanとしたいクラス ▸ 設定クラス (Java Config) @Componentが
 付いたクラスを探す
 パッケージ

Slide 18

Slide 18 text

(C) CASAREAL, Inc. All rights reserved. #jsug Bean定義⽅法① コンポーネントスキャン ▸ ίϯϙʔωϯτεΩϟϯ範囲は、basePackagesで
 指定したパッケージのサブパッケージ以下も含む 18 @Configuration @ComponentScan( basePackages = "com.example") public class AppConfig {} com example aaa bbb ccc スキャン範囲

Slide 19

Slide 19 text

(C) CASAREAL, Inc. All rights reserved. #jsug Bean定義⽅法① コンポーネントスキャン ▸ basePackagesを指定しなかった場合、
 @ComponentScanが付いたクラスのパッケージ
 がbasePackagesとなる 19 package com.example.config; @Configuration @ComponentScan // basePackages無し public class AppConfig {} これが basePackages になる!

Slide 20

Slide 20 text

(C) CASAREAL, Inc. All rights reserved. #jsug Bean定義⽅法② Java Config ▸ Java Configクラスにメソッドを作成し、
 @Beanを付加する
 → メソッドの戻り値がBeanになる 20 // @ComponentScanは不要 @Configuration public class AppConfig { @Bean public Hoge hoge() { return new Hoge(); } } // @Componentは不要 public class Hoge { ... }

Slide 21

Slide 21 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナを作る・Beanを取得する ▸ Java Configクラスを指定して
 ApplicationContext (=コンテナ)を作成 ▸ コンポーネントスキャン・Java Configどちらでも共通 ▸ getBean()でBeanを取得できる 21 // コンテナの作成 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // BeanをDIコンテナから取得(引数は欲しいBeanのデータ型) Hoge hoge = context.getBean(Hoge.class);

Slide 22

Slide 22 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナ作成で⾏われること ▸ コンポーネントスキャンの場合 1. @Componentが付いたクラスを探す 2. ⾒つけたらインスタンス化 3. コンテナに保存 ▸ Java Configの場合 1. @Beanメソッドを実⾏ 2. 戻り値をコンテナに保存 22 コンテナ作成は
 重い処理なので、
 1度コンテナを
 作成したら
 それを使い回す! ※࣮ࡍʹ͸ɺΠϯελϯεੜ੒ͷλΠϛϯά͸
 ɹείʔϓʢޙड़ʣʹΑͬͯҟͳΓ·͢ɻ
 ɹ͜͜Ͱઆ໌͍ͯ͠Δͷ͸singletonείʔϓͷ৔߹Ͱ͢

Slide 23

Slide 23 text

(C) CASAREAL, Inc. All rights reserved. #jsug Spring Bootの場合 23 package com.example; @SpringBootApplication public class MyApplication { public static void main(String[] args) { // コンテナの作成 ApplicationContext context = SpringApplication.run(MyApplication.class); } } これがbasePackages @Configuration @ComponentScan @EnableAutoConfiguration を組み合わせたアノテーション ※@EnableAutoConfigurationについては下記資料を参照
  https://www.slideshare.net/masatoshitada7/spring-boot-jjug

Slide 24

Slide 24 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナのまとめ ▸ コンテナ=インスタンス(Bean)の⼊れ物 ▸ コンポーネントスキャン ▸ @ComponentでBeanにするクラスを指定、 @ComponentScanで探す範囲を指定 ▸ Java Config ▸ @Beanを付加したメソッドの戻り値がBeanになる 24

Slide 25

Slide 25 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 25

Slide 26

Slide 26 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナの機能(再掲) ① Dependency Injection ② スコープの管理 ③ プロキシの作成 26

Slide 27

Slide 27 text

(C) CASAREAL, Inc. All rights reserved. #jsug Dependency Injectionとは ▸ ⽇本語で⾔うと 27 依存性の注⼊

Slide 28

Slide 28 text

(C) CASAREAL, Inc. All rights reserved. #jsug 28

Slide 29

Slide 29 text

(C) CASAREAL, Inc. All rights reserved. #jsug Dependency Injectionとは 29 依存性の注⼊ 必要なインスタンス (⾃動的)代⼊

Slide 30

Slide 30 text

(C) CASAREAL, Inc. All rights reserved. #jsug newしないで代⼊してもらう=DI 30 objA objB objA objB 代⼊ new ⭕ ❌ ▸ DIは、Bean⽣成時にコンテナが⾏う ▸ newしないことで、単体テストなどの時に
 インスタンスの差し替えが可能

Slide 31

Slide 31 text

(C) CASAREAL, Inc. All rights reserved. #jsug アノテーション+コンポーネントスキャンの場合 ▸ コンストラクタに@Autowiredを付加し、
 引数に欲しいBeanを指定 ▸ コンテナが適切なBeanを引数に代⼊してくれる 31 @Component public class Hoge { private final Fuga fuga; @Autowired public Hoge(Fuga fuga) { this.fuga = fuga; } } コンテナ Hoge Fuga DI DI ※クラス内にコンストラクタが1つのみの場合、
  @Autowiredは省略可能

Slide 32

Slide 32 text

(C) CASAREAL, Inc. All rights reserved. #jsug Java Configの場合 ▸ @Beanメソッドの引数に欲しいBeanを指定し、
 メソッド内に代⼊するコードを記述 ▸ コンテナが適切なBeanを引数に代⼊してくれる 32 @Configuration public class AppConfig { @Bean public Hoge hoge(Fuga fuga) { return new Hoge(fuga); } } コンテナ Hoge Fuga DI DI

Slide 33

Slide 33 text

(C) CASAREAL, Inc. All rights reserved. #jsug いろんなDI ▸ コンストラクタインジェクション 33 @Component public class Hoge { private final Fuga fuga; @Autowired public Hoge(Fuga fuga) { this.fuga = fuga; } } @Component public class Hoge { private Fuga fuga; @Autowired public setFuga(Fuga fuga) { this.fuga = fuga; } } @Component public class Hoge { @Autowired Fuga fuga; } ▸ setterインジェクション ▸ フィールドインジェクション 唯⼀Hogeを変更不能に できるので コンストラクタ インジェクション推奨 ※メソッドインジェクションとも呼びます ※変更不能(イミュータブル)=フィールドの値を書換不可能

Slide 34

Slide 34 text

(C) CASAREAL, Inc. All rights reserved. #jsug DIのまとめ ▸ DI=必要なインスタンスの代⼊ ▸ DIはコンテナがBeanを⽣成する際に⾏う ▸ コンストラクタにҾ਺Λ෇͚ͯ@Autowired
 or @Beanメソッドに引数 でBeanを代⼊可能 ▸ コンストラクタインジェクションが推奨 34

Slide 35

Slide 35 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 35

Slide 36

Slide 36 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナの機能(再掲) ① Dependency Injection ② スコープの管理 ③ プロキシの作成 36

Slide 37

Slide 37 text

(C) CASAREAL, Inc. All rights reserved. #jsug スコープとは ▸ コンテナが管理している、Beanの有効範囲 ▸ Beanがいつ⽣成され、いつ破棄されるか 37 スコープの種類 説明 singleton インスタンスは1つのみ(デフォルト) prototype 必要な時にインスタンスが毎回作られる request リクエストと同じ session セッションと同じ

Slide 38

Slide 38 text

(C) CASAREAL, Inc. All rights reserved. #jsug デフォルトはsingleton ▸ 1つのインスタンスが
 各所で使い回される ▸ フィールドで値を
 保持するのは厳禁!! ▸ セキュリティ事故に… 38 Bean 値 A B 値を
 保存 値が
 ⾒える

Slide 39

Slide 39 text

(C) CASAREAL, Inc. All rights reserved. #jsug スコープの考え⽅ ▸ ほとんどのBeanはsingletonでOK ▸ それ以外にしたくなったら、まず設計を⾒直す ▸ たまにsession使うかな・・・?くらい。 39

Slide 40

Slide 40 text

(C) CASAREAL, Inc. All rights reserved. #jsug スコープの指定⽅法① ▸ @Scope("スコープ名")をBeanに付加 40 @Scope("session") @Component public class Hoge { ... } @Configuration public class AppConfig { @Scope("request") @Bean public Hoge hoge() { ... } }

Slide 41

Slide 41 text

(C) CASAREAL, Inc. All rights reserved. #jsug スコープの指定⽅法② ▸ @RequestScope・@SessionScopeも⽤意されている 41 @SessionScope @Component public class Hoge { ... } @Configuration public class AppConfig { @RequestScope @Bean public Hoge hoge() { ... } }

Slide 42

Slide 42 text

(C) CASAREAL, Inc. All rights reserved. #jsug スコープのまとめ ▸ singleton・prototype・request・sessionの
 4種類 ▸ デフォルトはsingleton。値の保持厳禁! ▸ @Scopeで指定 42

Slide 43

Slide 43 text

(C) CASAREAL, Inc. All rights reserved. #jsug ⽬次 ① Springの歴史 ② Springのコンテナとは ③ Dependency Injectionとは ④ スコープとは ⑤ プロキシとは 43

Slide 44

Slide 44 text

(C) CASAREAL, Inc. All rights reserved. #jsug コンテナの機能(再掲) ① Dependency Injection ② スコープの管理 ③ プロキシの作成 44

Slide 45

Slide 45 text

(C) CASAREAL, Inc. All rights reserved. #jsug プロキシ プロキシとは ▸ 本来のBeanを
 ラップしたインスタンス ▸ インタフェースまたは
 継承を利⽤して作られる ▸ 他のBeanには
 プロキシがDIされる 45 <> Hoge HogeImpl (Bean) ※インタフェースの場合はJDK Proxy、
  継承の場合はCGLibを利⽤してプロキシが作られます

Slide 46

Slide 46 text

(C) CASAREAL, Inc. All rights reserved. #jsug プロキシの⽬的① AOP ▸ 本来の処理の前後に、割り込み処理を⾏う ▸ トランザクションの開始・終了、権限チェックなど 46 ※AOP : Aspect Oriented Programming // イメージコード public class HogeProxy implements Hoge { public void doSomething() { // 本来のBean Hoge hoge = ...; // 前処理の割り込み interceptor.doBefore(); // 本来の処理 hoge.doSomething(); // 後処理の割り込み interceptor.doAfter(); } }

Slide 47

Slide 47 text

(C) CASAREAL, Inc. All rights reserved. #jsug @Scope("singleton") @Component public class SingletonScopeBeanImpl implements SingletonScopeBean { private final RequestScopeBean rsb; @Autowired public SingletonScopeBean(RequestScopeBean rsb) { this.rsb = rsb; } public void doSomething() { rsb.execute(); } } プロキシの⽬的② スコープの違いを吸収 47 こちらもsingletonに なってしまう?
 → DIされるのは プロキシなので…

Slide 48

Slide 48 text

(C) CASAREAL, Inc. All rights reserved. #jsug // イメージコード public class RequestScopeBeanProxy implements RequestScopeBean { ApplicationContext context; @Override public void execute() { // 本来のBeanを毎回コンテナから取得している RequestScopeBean rsb = context.getBean(RequestScopeBean.class); rsb.execute(); } } プロキシの⽬的② スコープの違いを吸収 48 本来のBeanは 直接DIされないので、 スコープが違っていても ⼤丈夫! ※このプロキシはインタフェースで作成していますが、
  継承の場合でも同様です

Slide 49

Slide 49 text

(C) CASAREAL, Inc. All rights reserved. #jsug 誰がプロキシを作っているか ▸ BeanPostProcessorがプロキシを作っている ▸ コンテナがBeanインスタンスを⽣成した直後に実⾏ 49 HogeImpl (Bean) BeanPost Processor プロキシ HogeImpl (Bean)

Slide 50

Slide 50 text

(C) CASAREAL, Inc. All rights reserved. #jsug どのBeanにプロキシが作られるか ① AOPを利⽤しているBean ▸ @Transactional、@PreAuthorize、@Cachable、 @Retryableなど ② @ScopeでproxyMode = TARGET_CLASS
 またはINTERFACESが指定されているBean ▸ @RequestScopeや@SessionScopeは、
 デフォルトでTARGET_CLASSが指定されている 50

Slide 51

Slide 51 text

(C) CASAREAL, Inc. All rights reserved. #jsug プロキシのまとめ ▸ プロキシ=本来のBeanをラップしたインスタンス ▸ インタフェースまたは継承を利⽤して作られる ▸ AOPでの割り込み処理を実現する ▸ スコープの違いを吸収できる 51

Slide 52

Slide 52 text

(C) CASAREAL, Inc. All rights reserved. #jsug 本⽇のまとめ ▸ SpringはコンテナでBeanを管理している ▸ DIは必要なBeanの⾃動的代⼊ ▸ スコープは4種類。デフォルトはsingleton ▸ プロキシによって、割り込み処理と、
 スコープの違いの吸収が可能になる 52

Slide 53

Slide 53 text

(C) CASAREAL, Inc. All rights reserved. #jsug おすすめ市販書籍 ▸ 上記以外は、内容がやや古かったりするので
 個⼈的にはおすすめしません 53

Slide 54

Slide 54 text

(C) CASAREAL, Inc. All rights reserved. #jsug ご清聴ありがとうございました! 54