Submit Search
Upload
今さら聞けないDiとspring
•
19 likes
•
24,954 views
土岐 孝平
Follow
「JSUG勉強会 2017年その6」での発表会資料
Read less
Read more
Software
Report
Share
Report
Share
1 of 50
Download now
Download to read offline
Recommended
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
土岐 孝平
これから始めるSpringのwebアプリケーション
これから始めるSpringのwebアプリケーション
土岐 孝平
これからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきこと
土岐 孝平
入社1年目のプログラミング初心者がSpringを学ぶための手引き
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門
Satoshi Kubo
Spring超入門-Springと出会ってから1年半-
Spring超入門-Springと出会ってから1年半-
Ryosuke Uchitate
Spring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjug
Masatoshi Tada
Recommended
Springを何となく使ってる人が抑えるべきポイント
Springを何となく使ってる人が抑えるべきポイント
土岐 孝平
これから始めるSpringのwebアプリケーション
これから始めるSpringのwebアプリケーション
土岐 孝平
これからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきこと
土岐 孝平
入社1年目のプログラミング初心者がSpringを学ぶための手引き
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門
Satoshi Kubo
Spring超入門-Springと出会ってから1年半-
Spring超入門-Springと出会ってから1年半-
Ryosuke Uchitate
Spring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjug
Masatoshi Tada
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
Takeshi Ogawa
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
土岐 孝平
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
Masatoshi Tada
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
WataruOhno
RESTfulとは
RESTfulとは
星影 月夜
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
Masatoshi Tada
試験にでるSpring
試験にでるSpring
土岐 孝平
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
SpringBootTest入門
SpringBootTest入門
Yahoo!デベロッパーネットワーク
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
心 谷本
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
naoki koyama
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
ssuser070fa9
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
ssuser070fa9
What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
土岐 孝平
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Rakuten Group, Inc.
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
Daichi Koike
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
JustSystems Corporation
REST API のコツ
REST API のコツ
pospome
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Taku Miyakawa
Androidで学ぶ
Androidで学ぶ
Kensuke Onishi
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
Yusuke SAITO
More Related Content
What's hot
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
Takeshi Ogawa
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
土岐 孝平
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
Masatoshi Tada
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
WataruOhno
RESTfulとは
RESTfulとは
星影 月夜
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
Masatoshi Tada
試験にでるSpring
試験にでるSpring
土岐 孝平
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
SpringBootTest入門
SpringBootTest入門
Yahoo!デベロッパーネットワーク
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
心 谷本
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
naoki koyama
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
ssuser070fa9
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
ssuser070fa9
What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
土岐 孝平
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Rakuten Group, Inc.
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
Daichi Koike
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
JustSystems Corporation
REST API のコツ
REST API のコツ
pospome
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Taku Miyakawa
What's hot
(20)
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
RESTfulとは
RESTfulとは
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
試験にでるSpring
試験にでるSpring
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
SpringBootTest入門
SpringBootTest入門
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
新たなgitのブランチモデル「Git Feature Flow」!Git Flow,Git Hub Flow,Git Lab Flowを超えれるか?
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
AngularとSpring Bootで作るSPA + RESTful Web Serviceアプリケーション
What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
REST API のコツ
REST API のコツ
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
Similar to 今さら聞けないDiとspring
Androidで学ぶ
Androidで学ぶ
Kensuke Onishi
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
Yusuke SAITO
Tokyo r30 beginner
Tokyo r30 beginner
Takashi Minoda
2013講義1
2013講義1
ytanno
2010 icse-an analysis of the variability in forty preprocessor-based software...
2010 icse-an analysis of the variability in forty preprocessor-based software...
n-yuki
第一回Android training4desinger
第一回Android training4desinger
Kengo Suzuki
AndroidでDIxAOP
AndroidでDIxAOP
nfc research
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
聡 中川
Teclab3
Teclab3
Eikichi Yamaguchi
Tokyo r38
Tokyo r38
Takashi Minoda
動的なILの生成と編集
動的なILの生成と編集
terurou
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
Yoichi KIKUCHI
OpenStack Swift紹介
OpenStack Swift紹介
Kota Tsuyuzaki
DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃
Teruo Adachi
Similar to 今さら聞けないDiとspring
(14)
Androidで学ぶ
Androidで学ぶ
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
Tokyo r30 beginner
Tokyo r30 beginner
2013講義1
2013講義1
2010 icse-an analysis of the variability in forty preprocessor-based software...
2010 icse-an analysis of the variability in forty preprocessor-based software...
第一回Android training4desinger
第一回Android training4desinger
AndroidでDIxAOP
AndroidでDIxAOP
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
Teclab3
Teclab3
Tokyo r38
Tokyo r38
動的なILの生成と編集
動的なILの生成と編集
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
OpenStack Swift紹介
OpenStack Swift紹介
DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃
More from 土岐 孝平
SpringベースのCloud Native Application
SpringベースのCloud Native Application
土岐 孝平
Spring fest2020 spring-security
Spring fest2020 spring-security
土岐 孝平
Microserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探る
土岐 孝平
OpenID Connect入門
OpenID Connect入門
土岐 孝平
業務システムとマイクロサービス
業務システムとマイクロサービス
土岐 孝平
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
土岐 孝平
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
土岐 孝平
vFabricを触ろう
vFabricを触ろう
土岐 孝平
More from 土岐 孝平
(8)
SpringベースのCloud Native Application
SpringベースのCloud Native Application
Spring fest2020 spring-security
Spring fest2020 spring-security
Microserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探る
OpenID Connect入門
OpenID Connect入門
業務システムとマイクロサービス
業務システムとマイクロサービス
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
vFabricを触ろう
vFabricを触ろう
今さら聞けないDiとspring
1.
1 今さら聞けないDIとSpring 2017/08/30 日本Springユーザ会 土岐 孝平
2.
自己紹介 • 土岐 孝平 •
Springを使用したシステム開発の支援 • JavaやSpringの研修の講師 • 書籍の執筆 2 [改訂新版]Spring入門
3.
発表の趣旨 • 「自分はDIを使ってるらしいが、どの部分がDIでど んなメリットがあるのか分からない」という人はいま せんか? • DIという「考え方」を理解しましょう
⇒ 第1部 • SpringのDIを理解しましょう ⇒ 第2部 3
4.
第1部 DIという「考え方」を理解しよう 4
5.
DIの「D」とは? • Dependency:依存 • オブジェクトAは、オブジェクトBを使う •
オブジェクトAにとって、オブジェクトBは「依存するオ ブジェクト」 • DIの「D」は、「依存するオブジェクト」を指す※ 5 オブジェクトA オブジェクトB 使う(メソッド呼出) ※「具象クラスへの依存」という解釈もあります
6.
依存するオブジェクトの作成 • 依存するオブジェクトを「使う」には、依存するオブジ ェクトを「用意する」必要がある。 6 オブジェクトA オブジェクトB 使う(メソッド呼出) 「使う」ためには、 「用意する」必要が ある。 「用意する」とは? ・newで具象クラスのオブジェクトを生成する ・オブジェクトの初期設定や初期処理を行う
7.
サンプルプログラム • DAO(データアクセスオブジェクト)がデータソースを「使う」 – データソースを使って、コネクションプールしておいたコネクションを取 得する(getConnectionメソッドを呼出す) 7 FooDao データソースgetConnection DB 「使う」ためには、 「用意する」必要が ある。 「用意する」とは? ・newで具象クラスのオブジェク トを生成する ・接続先やプール数を設定する ≪interface≫ DataSource getConnection DataSourceA getConnection DataSourceB getConnection FooDao getFoo 使う
8.
依存するオブジェクトを用意する方法 • その①:使う側が自分で用意する • その②:使う側とは別のところで用意する 8
9.
その①:使う側が自分で用意する • 使う側のプログラムが長くなる – 本質ではない処理が入り込む •
依存するオブジェクトの設定を変更したり、具象クラスを変更する場合は 、使う側のプログラムを修正する必要がある 9 public class FooDao { private DataSource dataSource; public FooDao() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxActive(50); dataSource.setMaxIdle(50); this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ 「用意する」 部分 「使う」部分 public class Main { public static void main(String[] args) { FooDao fooDao = new FooDao(); Foo foo = fooDao.findFoo(); ・・・ 【実行するときの例】
10.
依存するオブジェクトを変更した例 • テストが難しい – テストの度に修正が必要 –
修正漏れが発生する可能性があり危険 10 public class FooDao { private DataSource dataSource; public FooDao() { EmbeddedDatabase dataSource = new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2).build(); this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ プログラムの 修正が必要
11.
その②:使う側とは別のところで用意する • 使う側のプログラムがシンプルになる – 本質の処理に注力できる •
依存するオブジェクトの設定を変更したり、具象クラスを変更する場合に 、使う側のプログラムを修正する必要が無い 11 public class FooDao { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxActive(50); dataSource.setMaxIdle(50); FooDao fooDao = new FooDao(); fooDao.setDataSource(dataSource); Foo foo = fooDao.findFoo(); ・・・ 「用意する」 部分 「使う」部分
12.
依存するオブジェクトを変更した例 • テスト時に、使う側のプログラムを修正する必要が無い 12 public class
FooDao { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class MainForTest { public static void main(String[] args) { EmbeddedDatabase dataSource = new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2).build(); FooDao fooDao = new FooDao(); fooDao.setDataSource(dataSource); Foo foo = fooDao.findFoo(); ・・・ 「用意する」 部分 修正不要 「用意する」部分を 変更
13.
DIとは? • (依存するオブジェクトを)「用意する」部分と「使う」 部分を分離するためのテクニック(考え方) • 依存するオブジェクトを、使う側のオブジェクトとは「 別のところ」で作成してもらって、参照を設定(注入) してもらう 13 使う側 依存する オブジェクト 使う 別のところ ①用意する②設定(注入)する
14.
DIの「I」とは? • Injection:注入 • 依存するオブジェクトを注入する 14 public
class FooDao { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxActive(50); dataSource.setMaxIdle(50); FooDao fooDao = new FooDao(); fooDao.setDataSource(dataSource); Foo foo = fooDao.findFoo(); ・・・ 「注入する」部分
15.
WebアプリケーションとDI • WebアプリケーションのオブジェクトとDIの例 15 Controller Service
Dao データソース 別のところ ①用意する ②用意する・注入する ③用意する・注入する ④用意する・注入する 使う使う 使う • 使う側のテストが容易 – 例:Serviceをテストする際に、MockのDaoのオブジェクトを注入して テストする Service Dao(Mock) 別のところ (テスト用) 使う 用意する注入する DB
16.
DIとシングルトン • DIの仕組みだとシングルトン(あるクラスのひとつのオブジェ クトを使いまわすこと)が容易 – コネクションプールのような共有すべきデータを共有できる –
不必要なオブジェクトの生成を避ける 16 XxxDao YyyDao ZzzDao データソース 別のところ 使う 使う 使う ②注入する ③注入する ④注入する ①用意する シングルトン
17.
留意点 • すべてのオブジェクトをDIする訳ではない • メソッド呼出の度に作成するようなオブジェクト(フィールドで 保持できないオブジェクト)はDIに適さない –
例:Entityのオブジェクト 17 public class FooDao { private DataSource dataSource; ・・・ public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); PreparedStatement ps = con.prepareStatement("select * from foo ..."); ・・・ ResultSet rs = ps.executeQuery(); Foo foo = null; while(rs.next()) { foo = new Foo(); foo.setName(rs.getString("name")); foo.setAge(rs.getInt("age")); } ・・・ return foo; } メソッド呼出の度に作成するオブ ジェクト
18.
まとめ • DIとは、(依存するオブジェクトを)「用意する」部分と 「使う」部分を分離するためのテクニック(考え方) – 依存するオブジェクトを、使う側のオブジェクトとは「別のと ころ」で用意してもらって、注入してもらう –
依存するオブジェクトを変更する際に、使う側のプログラ ムを修正する必要が無い • すべてのオブジェクトをDIする訳ではない 18
19.
クイズ 19
20.
DIを適用してる? 20 public class DataSourceFactory
{ private static DataSource dataSource; static { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxTotal(50); dataSource.setMaxIdle(50); dataSource.setMinIdle(10); DataSourceFactory.dataSource = dataSource; } public static DataSource getDataSource() { return dataSource; } } public class FooDao { private DataSource dataSource; public FooDao() { this.dataSource = DataSourceFactory.getDataSource(); } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { FooDao fooDao = new FooDao(); Foo foo = fooDao.findFoo(); System.out.println(foo); } }
21.
DIを適用してる? 21 public class DataSourceFactory
{ private static DataSource dataSource; static { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxTotal(50); dataSource.setMaxIdle(50); dataSource.setMinIdle(10); DataSourceFactory.dataSource = dataSource; } public static DataSource getDataSource() { return dataSource; } } public class FooDao { private DataSource dataSource; public FooDao() { this.dataSource = DataSourceFactory.getDataSource(); } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { FooDao fooDao = new FooDao(); Foo foo = fooDao.findFoo(); System.out.println(foo); } } 答え:適用していません 依存するオブジェクトを 自分で取得しています。 DIの場合、取得するのはなく、 「注入」してもらいます。
22.
DIを適用してる?その2 22 public class ObjectFactory
{ private static FooDao fooDao; static { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxTotal(50); dataSource.setMaxIdle(50); dataSource.setMinIdle(10); fooDao = new FooDao(); fooDao.setDataSource(dataSource); } public static FooDao getFooDao() { return fooDao; } } public class FooDao { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { FooDao fooDao = ObjectFactory.getFooDao(); Foo foo = fooDao.findFoo(); System.out.println(foo); } }
23.
DIを適用してる?その2 23 public class ObjectFactory
{ private static FooDao fooDao; static { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxTotal(50); dataSource.setMaxIdle(50); dataSource.setMinIdle(10); fooDao = new FooDao(); fooDao.setDataSource(dataSource); } public static FooDao getFooDao() { return fooDao; } } public class FooDao { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public Foo findFoo() throws Exception { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ public class Main { public static void main(String[] args) { FooDao fooDao = ObjectFactory.getFooDao(); Foo foo = fooDao.findFoo(); System.out.println(foo); } } 答え:適用しています 依存するオブジェクトを、 自分で用意してないし、 取得もしていません。 「注入」してもらってます。
24.
第2部 SpringのDIを理解しよう 24
25.
SpringのDI • Springは、「別のところ」を効率よく柔軟に作成する 機能を提供する 25 使う側 依存する オブジェクト 使う 別のところ ①用意する②設定(注入)する Springが機能を 提供
26.
Springの用語 • Bean – SpringのDIで作られたオブジェクトのこと •
コンフィグレーション – Beanの定義情報。どのクラスのBeanを用意するか?どのBeanを注入する か?などを定義する • DIコンテナ – Beanの入れ物。コンフィグレーションに従ってBeanを作成し、IDを割り振って 管理する。IDや型を指定してBeanを取得することも可能。 26 DIコンテナ コンフィグレー ション Bean Bean ID:foo ID:bar
27.
コンフィグレーションの手段 • XML • JavaConfig •
アノテーション 27
28.
XML • Springの誕生時からサポートされている 28 package sample; public
class FooService { private FooDao fooDao; public void setFooDao(FooDao fooDao) { this.fooDao = fooDao; } ・・・ } package sample; public class FooDao { ・・・ } <bean id="fooService" class="sample.FooService"> <property name="fooDao" ref="fooDao"/> </bean> <bean id="fooDao" class="sample.FooDao"> </bean> DIコンテナ FooService FooDao ID:fooService ID:fooDao XML public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("sample/foo.xml"); FooService fooService = ctx.getBean(FooService.class); ・・・ } } 【参考】実行の例
29.
JavaConfig • Spring3.0からサポート 29 package sample; public
class FooService { private FooDao fooDao; public void setFooDao(FooDao fooDao) { this.fooDao = fooDao; } ・・・ } package sample; public class FooDao { ・・・ } @Configuration public class FooConfig { @Bean public FooService fooService() { FooService fooService = new FooService(); fooService.setFooDao(fooDao()); return fooService; } @Bean public FooDao fooDao() { return new FooDao(); } } DIコンテナ FooService FooDao ID:fooService ID:fooDao ・Bean IDは、メソッド名の「fooDao」となる JavaConfig
30.
アノテーション • Spring2.5からサポート 30 package sample; @Service public
class FooService { @Autowired private FooDao fooDao; ・・・ } package sample; @Repository public class FooDao { ・・・ } <context:component-scan base-package=“sample"/> DIコンテナ FooService FooDao ID:fooService ID:fooDao @Configuration @ComponentScan(basePackages="sample") public class FooConfig { } もしくは ・Bean IDは、クラス名の先頭文字を小文字にし た「fooDao」となる。 ・value属性値で明示的に指定することも可能 例)@Repository(“fooDaoCustom”) XML JavaConfig
31.
ステレオタイプアノテーション • コンポーネントスキャンでBeanを用意する際の目印 となる • @Componentをベースにして、複数の種類がある –
Beanの役割に応じて使い分ける – Beanを用意する以外に、若干の付加機能が付く 31 @Controller @Component @Service @Repository @Configration
32.
コンフィグレーションの手段:補足1/2 • コンフグレーションの手段が異なっても、結果は同じ – Beanが用意・注入されて、DIコンテナで管理される •
コンフグレーションの手段は、ミックスできる 32 DIコンテナ FooService FooDao ID:fooService ID:fooDao XML アノテーション JavaConfig
33.
コンフィグレーションの手段:補足2/2 • @Autowiredは、XML※やJavaConfigで用意したBeanに対 しても適用される 33 ※<context:annotation-config/>の記述が必要 package sample; public
class FooService { @Autowired private FooDao fooDao; ・・・ } package sample; public class FooDao { ・・・ } @Configuration public class FooConfig { @Bean public FooService fooService() { return new FooService(); } @Bean public FooDao fooDao() { return new FooDao(); } } DIコンテナ FooService FooDao ID:fooService ID:fooDao JavaConfig
34.
コンフィグレーションの手段の使い分け1/2 34 • 業務個別のBean(Controller、Service、Dao)はアノテーション – Beanの数が増えてもメンテナンスが楽 •
裏方のBeanはXMLもしくはJavaConfig – 環境(テスト環境・本番環境など)ごとにコンフィグレーションを用意できて切替が簡単 – サードパーティのクラスはアノテーションがつけられない @Controller Controller @Service Service @Repository Dao Transaction Manager DataSource 本番用 テスト用 業務個別 裏方 注入する 注入する Transaction Manager DataSource アノテーション XML or JavaConfig ・・・ ・・・
35.
コンフィグレーションの手段の使い分け2/2 35 package sample; @Service public class
FooService { @Autowired private FooDao fooDao; public Foo getFoo() { Foo foo = fooDao.findFoo(); ・・・ package sample; @Repository public class FooDao { @Autowired private DataSource dataSource; public Foo findFoo() { Connection con = dataSource.getConnection(); con.prepareStatement("select * from foo ..."); ・・・ package sample; @Controller public class FooController { @Autowired private FooService fooService; @RequestMapping("/showFoo") public String showFoo() { Foo foo = fooService.getFoo(); ・・・ @Configuration @ComponentScan(basePackages="sample") public class AppConfig { @Bean public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/foo"); dataSource.setUsername("foo"); dataSource.setPassword("foo123"); dataSource.setMaxActive(50); dataSource.setMaxIdle(50); dataSource.setMinIdle(10); return dataSource; } } Controller Service Dao DataSource
36.
DIコンテナの作成 • スタンドアロンアプリ(Webアプリじゃないアプリ)実行時 • JUnit実行時 •
APサーバ実行時 • Spring Boot実行時 36
37.
スタンドアロンアプリ実行時 • XMLのコンフィグレーションを読込む場合 • JavaConfigのコンフィグレーションを読込む場合 37 ApplicationContext
ctx = new ClassPathXmlApplicationContext("sample/foo.xml"); FooService fooService = ctx.getBean(FooService.class); Foo foo = fooService.getFoo(); ・・・ ApplicationContext ctx = new AnnotationConfigApplicationContext(FooConfig.class); FooService fooService = ctx.getBean(FooService.class); Foo foo = fooService.getFoo(); ・・・
38.
JUnit実行時 38 public class FooServiceTest
{ private FooService fooService; @Before public void setup() { ApplicationContext ctx = new AnnotationConfigApplicationContext(FooTestConfig.class); fooService = ctx.getBean(FooService.class); } @Test public void testGetFoo() { Foo foo = fooService.getFoo(); assertNotNull(foo); } } @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=FooTestConfig.class) public class FooServiceTest { @Autowired private FooService fooService; @Test public void testGetFoo() { Foo foo = fooService.getFoo(); assertNotNull(foo); } }より簡潔な書き方
39.
APサーバ実行時 39 web.xml ・・・ AppConfig.class ・・・ Springが提供するServlet やListenerを登録する際に、 コンフィグレーションのファ イルを指定できる Tomcat DIコンテナ Controller Service Dao
DataSource SpringのServletやListener がDIコンテナを作成する ブラウザ /showFoo Tomcat起動後は、DIコンテナ が作成済みなので、 Controllerにアクセスできる
40.
Spring Boot実行時 40 package sample; @SpringBootApplication public
class FooApplication { public static void main(String[] args) { SpringApplication.run(FooApplication.class, args); } } 指定したコンフィグレーションのファ イル(自分自身)を読込んでDIコンテ ナが作成される。合わせて、Tomcat も起動する。 @SpringBootApplicationには、 @Configration、@ComponentScanが 含まれている。basePackagesの指定 が無いため、アノテーションを付加し たクラス(FooApplication)のパッケー ジ(sample)がベースパッケージとなり、 配下のクラス(サブパッケージも含む) がコンポーネントスキャンされる。 @SpringBootApplication FooApplication sample @Controller FooController @Service FooService @Repository FooDao @Configuration AppConfig Tomcat DIコンテナ Controller Service Dao DataSource
41.
まとめ • SpringのDIは、 オブジェクトを用意して注入する部 分を、効率よく柔軟に作成する機能を提供する •
コンフィグレーションの手段は3つある – 使い分けが可能 • DIコンテナを作成する方法はケースバイケースでい ろいろある 41
42.
クイズ 42
43.
43 【問題】 以下のコードと等しい記述はどれでしょう?1つ選んでください @Configuration public class FooConfig
{ @Bean public FooService fooService() { return new FooServiceImpl(); } } 【選択肢】 (A). <bean id="fooConfig" class="com.foo.FooService"/> (B). <bean id="fooService" class="com.foo.FooServiceImpl"/> (C). <bean id="fooConfig" class="com.foo.FooServiceImpl"/> (D). 上記のいずれも該当しない。@Beanはname属性が必須である
44.
44 【問題】 以下のコードと等しい記述はどれでしょう?1つ選んでください @Configuration public class FooConfig
{ @Bean public FooService fooService() { return new FooServiceImpl(); } } 【選択肢】 (A). <bean id="fooConfig" class="com.foo.FooService"/> (B). <bean id="fooService" class="com.foo.FooServiceImpl"/> (C). <bean id="fooConfig" class="com.foo.FooServiceImpl"/> (D). 上記のいずれも該当しない。@Beanはname属性が必須である
45.
実行結果はどうなる? 45 @Configuration @ComponentScan(basePackages=“sample") public class FooConfig
{ } public interface FooDao { public void foo(); } package sample; @Repository public class FooDaoA implements FooDao { public void foo() { System.out.print("A"); } } package sample; @Repository public class FooDaoB implements FooDao { public void foo() { System.out.print(“B"); } } package sample; @Service public class FooService { @Autowired private FooDao fooDao; public void execute() { fooDao.foo(); } } public class Main { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(FooConfig.class); FooService fooService = ctx.getBean(FooService.class); fooService.execute(); } } (A) “A”と表示される (B) “B”と表示される (C) “AB”と表示される (D) 例外が発生する
46.
実行結果はどうなる? 46 @Configuration @ComponentScan(basePackages=“sample") public class FooConfig
{ } public interface FooDao { public void foo(); } package sample; @Repository public class FooDaoA implements FooDao { public void foo() { System.out.print("A"); } } package sample; @Repository public class FooDaoB implements FooDao { public void foo() { System.out.print(“B"); } } package sample; @Service public class FooService { @Autowired private FooDao fooDao; public void execute() { fooDao.foo(); } } public class Main { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(FooConfig.class); FooService fooService = ctx.getBean(FooService.class); fooService.execute(); } } (A) “A”と表示される (B) “B”と表示される (C) “AB”と表示される (D) 例外が発生する FooDaoを実装したBeanが 2つ存在するため、どれを 注入すればよいか分から ない
47.
Bean IDを指定して@Autowireが可能 47 package sample; @Service public
class FooService { @Autowired @Qualifier("fooDaoA") private FooDao fooDao; public void execute() { fooDao.foo(); } } @QualifierでBean IDを指 定できる
48.
さいごに • DIが分かれば、Springの理解力が飛躍的に上がります – Springが提供する様々な機能は、DIの考え方・仕組みで成り立って いる •
裏でやってることがイメージし易い • AOPが分かると、さらに理解力が上がります 48 [改訂新版]Spring入門 Spring徹底入門
49.
49 ご清聴ありがとうございました
50.
50 ライセンスについて • JSUGマスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生 作品)の複製・頒布・表示・上演を認めます。 • 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。 •
本作品のライセンスを遵守する限り、派生作品を頒布することを許可します。
Download now