Upgrade to Pro — share decks privately, control downloads, hide ads and more …

コンテナから紐解く本当のSpring入門 #jsug / Understanding Spring Container

コンテナから紐解く本当のSpring入門 #jsug / Understanding Spring Container

2019-08-28
JSUG勉強会で発表した資料です。Springのコア機能であるコンテナ・DI・スコープ・プロキシを解説しています。

Masatoshi Tada

August 28, 2019
Tweet

More Decks by Masatoshi Tada

Other Decks in Technology

Transcript

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

    View full-size slide

  2. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    このセッションについて
    ▸ Springの基礎となる「コンテナ」「DI」に

    ついて、基礎から分かりやすく解説します
    ▸ 基本的に初⼼者向けですが、

    Springを利⽤している全ての⽅が対象です
    2

    View full-size slide

  3. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    ⾃⼰紹介
    ▸ 多⽥真敏(@suke_masa)
    ▸ 研修トレーナー@カサレアル
    ▸ Spring / Java EE / Microservices

    / Cloud Foundry
    ▸ Pivotal認定講師
    ▸ ⽇本Springユーザ会スタッフ
    3

    View full-size slide

  4. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    お願い:⾳にご注意ください!
    ▸ メモを取る際のキータッチは優しくお願いします。
    ▸ スライドは後ほどWebにアップしますので、

    スライドの写真撮影はなるべくしないでください。
    ▸ どうしても撮影されたい場合は、

    Microsoft Pixなど⾳のしないカメラアプリを

    ご利⽤ください。
    4

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  7. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    Springの誕⽣
    ▸ 2002年、Rod Johnson⽒が⾃著の
    サンプルプログラムとして作成
    ▸ 重くて複雑だった当時のJ2EE・EJBに

    対するアンチテーゼだった
    ▸ Johnson⽒が会社を⽴ち上げたり、

    買収されたり紆余曲折あって、

    現在はPivotal社が中⼼に開発
    7

    View full-size slide

  8. (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以上も対応)、リアクティブ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  11. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    Springはコンテナを持っている
    ▸ コンテナ=インスタンスの⼊れ物
    ▸ Bean=コンテナで管理されたインスタンス
    11
    コンテナ
    Bean Bean Bean
    Bean Bean
    ※「インスタンス」とは、

     もちろんJavaのインスタンスの

     ことです
    必要に応じて

    取り出して使う

    View full-size slide

  12. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    コンテナは全Springプロダクトのベース
    ▸ 例:Spring MVCはDispatcherServlet内に

      コンテナを持っている
    12
    DispatcherServlet
    コンテナ
    Bean Bean Bean
    12
    必要に応じて

    取り出して使う

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    Bean定義⽅法① コンポーネントスキャン
    ▸ コンポーネントスキャン

    =指定されたパッケージから@Componentが

     付いたクラスを探す
    ▸ ⾒つけたらインスタンス化→コンテナに保存
    15

    View full-size slide

  16. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    ▸ 右記のアノテーションを

    クラスに付けると、

    @Componentを付けた

    ことと同じになる
    ▸ クラスの役割に応じて

    変える
    16
    @Repository
    @Service
    @Controller
    @RestController
    @Configuration
    @ControllerAdvice
    @RestControllerAdvice
    ɾɾɾ
    Bean定義⽅法① コンポーネントスキャン
    ※これらのアノテーションのソースコードを読むと、

     @Componentが付いていることが分かります

    View full-size slide

  17. (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が

    付いたクラスを探す

    パッケージ

    View full-size slide

  18. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    Bean定義⽅法① コンポーネントスキャン
    ▸ ίϯϙʔωϯτεΩϟϯ範囲は、basePackagesで

    指定したパッケージのサブパッケージ以下も含む
    18
    @Configuration
    @ComponentScan(
    basePackages =
    "com.example")
    public class AppConfig {}
    com
    example
    aaa
    bbb
    ccc
    スキャン範囲

    View full-size slide

  19. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    Bean定義⽅法① コンポーネントスキャン
    ▸ basePackagesを指定しなかった場合、

    @ComponentScanが付いたクラスのパッケージ

    がbasePackagesとなる
    19
    package com.example.config;
    @Configuration
    @ComponentScan // basePackages無し
    public class AppConfig {}
    これが
    basePackages
    になる!

    View full-size slide

  20. (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 {
    ...
    }

    View full-size slide

  21. (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);

    View full-size slide

  22. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    コンテナ作成で⾏われること
    ▸ コンポーネントスキャンの場合
    1. @Componentが付いたクラスを探す
    2. ⾒つけたらインスタンス化
    3. コンテナに保存
    ▸ Java Configの場合
    1. @Beanメソッドを実⾏
    2. 戻り値をコンテナに保存
    22
    コンテナ作成は

    重い処理なので、

    1度コンテナを

    作成したら

    それを使い回す!
    ※࣮ࡍʹ͸ɺΠϯελϯεੜ੒ͷλΠϛϯά͸

    ɹείʔϓʢޙड़ʣʹΑͬͯҟͳΓ·͢ɻ

    ɹ͜͜Ͱઆ໌͍ͯ͠Δͷ͸singletonείʔϓͷ৔߹Ͱ͢

    View full-size slide

  23. (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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    newしないで代⼊してもらう=DI
    30
    objA
    objB
    objA
    objB
    代⼊
    new


    ▸ DIは、Bean⽣成時にコンテナが⾏う
    ▸ newしないことで、単体テストなどの時に

    インスタンスの差し替えが可能

    View full-size slide

  31. (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は省略可能

    View full-size slide

  32. (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

    View full-size slide

  33. (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を変更不能に
    できるので
    コンストラクタ
    インジェクション推奨
    ※メソッドインジェクションとも呼びます
    ※変更不能(イミュータブル)=フィールドの値を書換不可能

    View full-size slide

  34. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    DIのまとめ
    ▸ DI=必要なインスタンスの代⼊
    ▸ DIはコンテナがBeanを⽣成する際に⾏う
    ▸ コンストラクタにҾ਺Λ෇͚ͯ@Autowired

    or @Beanメソッドに引数 でBeanを代⼊可能
    ▸ コンストラクタインジェクションが推奨
    34

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  38. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    デフォルトはsingleton
    ▸ 1つのインスタンスが

    各所で使い回される
    ▸ フィールドで値を

    保持するのは厳禁!!
    ▸ セキュリティ事故に…
    38
    Bean

    A B
    値を

    保存
    値が

    ⾒える

    View full-size slide

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

    View full-size slide

  40. (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() { ... }
    }

    View full-size slide

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

    View full-size slide

  42. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    スコープのまとめ
    ▸ singleton・prototype・request・sessionの

    4種類
    ▸ デフォルトはsingleton。値の保持厳禁!
    ▸ @Scopeで指定
    42

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  45. (C) CASAREAL, Inc. All rights reserved.
    #jsug
    プロキシ
    プロキシとは
    ▸ 本来のBeanを

    ラップしたインスタンス
    ▸ インタフェースまたは

    継承を利⽤して作られる
    ▸ 他のBeanには

    プロキシがDIされる
    45
    <>
    Hoge
    HogeImpl
    (Bean)
    ※インタフェースの場合はJDK Proxy、

     継承の場合はCGLibを利⽤してプロキシが作られます

    View full-size slide

  46. (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();
    }
    }

    View full-size slide

  47. (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されるのは
    プロキシなので…

    View full-size slide

  48. (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されないので、
    スコープが違っていても
    ⼤丈夫!
    ※このプロキシはインタフェースで作成していますが、

     継承の場合でも同様です

    View full-size slide

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

    View full-size slide

  50. (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

    View full-size slide

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

    View full-size slide

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

    スコープの違いの吸収が可能になる
    52

    View full-size slide

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

    個⼈的にはおすすめしません
    53

    View full-size slide

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

    View full-size slide