Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
1
今さら聞けないDIとSpring
2017/08/30
日本Springユーザ会
土岐 孝平
自己紹介
• 土岐 孝平
• Springを使用したシステム開発の支援
• JavaやSpringの研修の講師
• 書籍の執筆
2
[改訂新版]Spring入門
発表の趣旨
• 「自分はDIを使ってるらしいが、どの部分がDIでど
んなメリットがあるのか分からない」という人はいま
せんか?
• DIという「考え方」を理解しましょう ⇒ 第1部
• SpringのDIを理解しましょう ⇒ 第2部
3
第1部
DIという「考え方」を理解しよう
4
DIの「D」とは?
• Dependency:依存
• オブジェクトAは、オブジェクトBを使う
• オブジェクトAにとって、オブジェクトBは「依存するオ
ブジェクト」
• DIの「D」は、「依存するオブジェクト」を指す※
5
オブジェクトA オ...
依存するオブジェクトの作成
• 依存するオブジェクトを「使う」には、依存するオブジ
ェクトを「用意する」必要がある。
6
オブジェクトA オブジェクトB
使う(メソッド呼出)
「使う」ためには、
「用意する」必要が
ある。
「用意する」とは?
...
サンプルプログラム
• DAO(データアクセスオブジェクト)がデータソースを「使う」
– データソースを使って、コネクションプールしておいたコネクションを取
得する(getConnectionメソッドを呼出す)
7
FooDao
データソースg...
依存するオブジェクトを用意する方法
• その①:使う側が自分で用意する
• その②:使う側とは別のところで用意する
8
その①:使う側が自分で用意する
• 使う側のプログラムが長くなる
– 本質ではない処理が入り込む
• 依存するオブジェクトの設定を変更したり、具象クラスを変更する場合は
、使う側のプログラムを修正する必要がある
9
public class F...
依存するオブジェクトを変更した例
• テストが難しい
– テストの度に修正が必要
– 修正漏れが発生する可能性があり危険
10
public class FooDao {
private DataSource dataSource;
publi...
その②:使う側とは別のところで用意する
• 使う側のプログラムがシンプルになる
– 本質の処理に注力できる
• 依存するオブジェクトの設定を変更したり、具象クラスを変更する場合に
、使う側のプログラムを修正する必要が無い
11
public c...
依存するオブジェクトを変更した例
• テスト時に、使う側のプログラムを修正する必要が無い
12
public class FooDao {
private DataSource dataSource;
public void setDataSo...
DIとは?
• (依存するオブジェクトを)「用意する」部分と「使う」
部分を分離するためのテクニック(考え方)
• 依存するオブジェクトを、使う側のオブジェクトとは「
別のところ」で作成してもらって、参照を設定(注入)
してもらう
13
使う側...
DIの「I」とは?
• Injection:注入
• 依存するオブジェクトを注入する
14
public class FooDao {
private DataSource dataSource;
public void setDataSour...
WebアプリケーションとDI
• WebアプリケーションのオブジェクトとDIの例
15
Controller Service Dao データソース
別のところ
①用意する
②用意する・注入する
③用意する・注入する
④用意する・注入する
使う使...
DIとシングルトン
• DIの仕組みだとシングルトン(あるクラスのひとつのオブジェ
クトを使いまわすこと)が容易
– コネクションプールのような共有すべきデータを共有できる
– 不必要なオブジェクトの生成を避ける
16
XxxDao
YyyDa...
留意点
• すべてのオブジェクトをDIする訳ではない
• メソッド呼出の度に作成するようなオブジェクト(フィールドで
保持できないオブジェクト)はDIに適さない
– 例:Entityのオブジェクト
17
public class FooDao ...
まとめ
• DIとは、(依存するオブジェクトを)「用意する」部分と
「使う」部分を分離するためのテクニック(考え方)
– 依存するオブジェクトを、使う側のオブジェクトとは「別のと
ころ」で用意してもらって、注入してもらう
– 依存するオブジェク...
クイズ
19
DIを適用してる?
20
public class DataSourceFactory {
private static DataSource dataSource;
static {
BasicDataSource dataSource = ...
DIを適用してる?
21
public class DataSourceFactory {
private static DataSource dataSource;
static {
BasicDataSource dataSource = ...
DIを適用してる?その2
22
public class ObjectFactory {
private static FooDao fooDao;
static {
BasicDataSource dataSource = new Basic...
DIを適用してる?その2
23
public class ObjectFactory {
private static FooDao fooDao;
static {
BasicDataSource dataSource = new Basic...
第2部
SpringのDIを理解しよう
24
SpringのDI
• Springは、「別のところ」を効率よく柔軟に作成する
機能を提供する
25
使う側
依存する
オブジェクト
使う
別のところ
①用意する②設定(注入)する
Springが機能を
提供
Springの用語
• Bean
– SpringのDIで作られたオブジェクトのこと
• コンフィグレーション
– Beanの定義情報。どのクラスのBeanを用意するか?どのBeanを注入する
か?などを定義する
• DIコンテナ
– Bean...
コンフィグレーションの手段
• XML
• JavaConfig
• アノテーション
27
XML
• Springの誕生時からサポートされている
28
package sample;
public class FooService {
private FooDao fooDao;
public void setFooDao(FooD...
JavaConfig
• Spring3.0からサポート
29
package sample;
public class FooService {
private FooDao fooDao;
public void setFooDao(Foo...
アノテーション
• Spring2.5からサポート
30
package sample;
@Service
public class FooService {
@Autowired
private FooDao fooDao;
・・・
}
pa...
ステレオタイプアノテーション
• コンポーネントスキャンでBeanを用意する際の目印
となる
• @Componentをベースにして、複数の種類がある
– Beanの役割に応じて使い分ける
– Beanを用意する以外に、若干の付加機能が付く
3...
コンフィグレーションの手段:補足1/2
• コンフグレーションの手段が異なっても、結果は同じ
– Beanが用意・注入されて、DIコンテナで管理される
• コンフグレーションの手段は、ミックスできる
32
DIコンテナ
FooService F...
コンフィグレーションの手段:補足2/2
• @Autowiredは、XML※やJavaConfigで用意したBeanに対
しても適用される
33
※<context:annotation-config/>の記述が必要
package sampl...
コンフィグレーションの手段の使い分け1/2
34
• 業務個別のBean(Controller、Service、Dao)はアノテーション
– Beanの数が増えてもメンテナンスが楽
• 裏方のBeanはXMLもしくはJavaConfig
– 環...
コンフィグレーションの手段の使い分け2/2
35
package sample;
@Service
public class FooService {
@Autowired
private FooDao fooDao;
public Foo g...
DIコンテナの作成
• スタンドアロンアプリ(Webアプリじゃないアプリ)実行時
• JUnit実行時
• APサーバ実行時
• Spring Boot実行時
36
スタンドアロンアプリ実行時
• XMLのコンフィグレーションを読込む場合
• JavaConfigのコンフィグレーションを読込む場合
37
ApplicationContext ctx = new ClassPathXmlApplication...
JUnit実行時
38
public class FooServiceTest {
private FooService fooService;
@Before
public void setup() {
ApplicationContext ...
APサーバ実行時
39
web.xml
・・・
AppConfig.class
・・・
Springが提供するServlet
やListenerを登録する際に、
コンフィグレーションのファ
イルを指定できる
Tomcat
DIコンテナ
Cont...
Spring Boot実行時
40
package sample;
@SpringBootApplication
public class FooApplication {
public static void main(String[] ar...
まとめ
• SpringのDIは、 オブジェクトを用意して注入する部
分を、効率よく柔軟に作成する機能を提供する
• コンフィグレーションの手段は3つある
– 使い分けが可能
• DIコンテナを作成する方法はケースバイケースでい
ろいろある
41
クイズ
42
43
【問題】
以下のコードと等しい記述はどれでしょう?1つ選んでください
@Configuration
public class FooConfig {
@Bean
public FooService fooService() {
retur...
44
【問題】
以下のコードと等しい記述はどれでしょう?1つ選んでください
@Configuration
public class FooConfig {
@Bean
public FooService fooService() {
retur...
実行結果はどうなる?
45
@Configuration
@ComponentScan(basePackages=“sample")
public class FooConfig {
}
public interface FooDao {
pu...
実行結果はどうなる?
46
@Configuration
@ComponentScan(basePackages=“sample")
public class FooConfig {
}
public interface FooDao {
pu...
Bean IDを指定して@Autowireが可能
47
package sample;
@Service
public class FooService {
@Autowired
@Qualifier("fooDaoA")
private Fo...
さいごに
• DIが分かれば、Springの理解力が飛躍的に上がります
– Springが提供する様々な機能は、DIの考え方・仕組みで成り立って
いる
• 裏でやってることがイメージし易い
• AOPが分かると、さらに理解力が上がります
48
...
49
ご清聴ありがとうございました
50
ライセンスについて
• JSUGマスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生
作品)の複製・頒布・表示・上演を認めます。
• 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒...
Upcoming SlideShare
Loading in …5
×

今さら聞けないDiとspring

19,378 views

Published on

「JSUG勉強会 2017年その6」での発表会資料

Published in: Software
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❶❶❶ http://bit.ly/2u6xbL5 ❶❶❶
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ♥♥♥ http://bit.ly/2u6xbL5 ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • I seemed to underperform in my mock exams - achieving D's/E's but after following your strategy and advice, I achieved a 'B' grade in my final GCSE maths exam. I was chuffed because this result enabled me to study A-Level Chemistry. I've used your revision principles again and this has helped me immensely in this subject. Thank you so much Jeevan.. my 'B' grade will definitely help me in applying for a Pharmacy' course at University...★★★ http://t.cn/AirraVnG
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

今さら聞けないDiとspring

  1. 1. 1 今さら聞けないDIとSpring 2017/08/30 日本Springユーザ会 土岐 孝平
  2. 2. 自己紹介 • 土岐 孝平 • Springを使用したシステム開発の支援 • JavaやSpringの研修の講師 • 書籍の執筆 2 [改訂新版]Spring入門
  3. 3. 発表の趣旨 • 「自分はDIを使ってるらしいが、どの部分がDIでど んなメリットがあるのか分からない」という人はいま せんか? • DIという「考え方」を理解しましょう ⇒ 第1部 • SpringのDIを理解しましょう ⇒ 第2部 3
  4. 4. 第1部 DIという「考え方」を理解しよう 4
  5. 5. DIの「D」とは? • Dependency:依存 • オブジェクトAは、オブジェクトBを使う • オブジェクトAにとって、オブジェクトBは「依存するオ ブジェクト」 • DIの「D」は、「依存するオブジェクト」を指す※ 5 オブジェクトA オブジェクトB 使う(メソッド呼出) ※「具象クラスへの依存」という解釈もあります
  6. 6. 依存するオブジェクトの作成 • 依存するオブジェクトを「使う」には、依存するオブジ ェクトを「用意する」必要がある。 6 オブジェクトA オブジェクトB 使う(メソッド呼出) 「使う」ためには、 「用意する」必要が ある。 「用意する」とは? ・newで具象クラスのオブジェクトを生成する ・オブジェクトの初期設定や初期処理を行う
  7. 7. サンプルプログラム • DAO(データアクセスオブジェクト)がデータソースを「使う」 – データソースを使って、コネクションプールしておいたコネクションを取 得する(getConnectionメソッドを呼出す) 7 FooDao データソースgetConnection DB 「使う」ためには、 「用意する」必要が ある。 「用意する」とは? ・newで具象クラスのオブジェク トを生成する ・接続先やプール数を設定する ≪interface≫ DataSource getConnection DataSourceA getConnection DataSourceB getConnection FooDao getFoo 使う
  8. 8. 依存するオブジェクトを用意する方法 • その①:使う側が自分で用意する • その②:使う側とは別のところで用意する 8
  9. 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. 依存するオブジェクトを変更した例 • テストが難しい – テストの度に修正が必要 – 修正漏れが発生する可能性があり危険 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. その②:使う側とは別のところで用意する • 使う側のプログラムがシンプルになる – 本質の処理に注力できる • 依存するオブジェクトの設定を変更したり、具象クラスを変更する場合に 、使う側のプログラムを修正する必要が無い 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. 依存するオブジェクトを変更した例 • テスト時に、使う側のプログラムを修正する必要が無い 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. 13. DIとは? • (依存するオブジェクトを)「用意する」部分と「使う」 部分を分離するためのテクニック(考え方) • 依存するオブジェクトを、使う側のオブジェクトとは「 別のところ」で作成してもらって、参照を設定(注入) してもらう 13 使う側 依存する オブジェクト 使う 別のところ ①用意する②設定(注入)する
  14. 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. 15. WebアプリケーションとDI • WebアプリケーションのオブジェクトとDIの例 15 Controller Service Dao データソース 別のところ ①用意する ②用意する・注入する ③用意する・注入する ④用意する・注入する 使う使う 使う • 使う側のテストが容易 – 例:Serviceをテストする際に、MockのDaoのオブジェクトを注入して テストする Service Dao(Mock) 別のところ (テスト用) 使う 用意する注入する DB
  16. 16. DIとシングルトン • DIの仕組みだとシングルトン(あるクラスのひとつのオブジェ クトを使いまわすこと)が容易 – コネクションプールのような共有すべきデータを共有できる – 不必要なオブジェクトの生成を避ける 16 XxxDao YyyDao ZzzDao データソース 別のところ 使う 使う 使う ②注入する ③注入する ④注入する ①用意する シングルトン
  17. 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. 18. まとめ • DIとは、(依存するオブジェクトを)「用意する」部分と 「使う」部分を分離するためのテクニック(考え方) – 依存するオブジェクトを、使う側のオブジェクトとは「別のと ころ」で用意してもらって、注入してもらう – 依存するオブジェクトを変更する際に、使う側のプログラ ムを修正する必要が無い • すべてのオブジェクトをDIする訳ではない 18
  19. 19. クイズ 19
  20. 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. 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. 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. 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. 24. 第2部 SpringのDIを理解しよう 24
  25. 25. SpringのDI • Springは、「別のところ」を効率よく柔軟に作成する 機能を提供する 25 使う側 依存する オブジェクト 使う 別のところ ①用意する②設定(注入)する Springが機能を 提供
  26. 26. Springの用語 • Bean – SpringのDIで作られたオブジェクトのこと • コンフィグレーション – Beanの定義情報。どのクラスのBeanを用意するか?どのBeanを注入する か?などを定義する • DIコンテナ – Beanの入れ物。コンフィグレーションに従ってBeanを作成し、IDを割り振って 管理する。IDや型を指定してBeanを取得することも可能。 26 DIコンテナ コンフィグレー ション Bean Bean ID:foo ID:bar
  27. 27. コンフィグレーションの手段 • XML • JavaConfig • アノテーション 27
  28. 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. 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. 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. 31. ステレオタイプアノテーション • コンポーネントスキャンでBeanを用意する際の目印 となる • @Componentをベースにして、複数の種類がある – Beanの役割に応じて使い分ける – Beanを用意する以外に、若干の付加機能が付く 31 @Controller @Component @Service @Repository @Configration
  32. 32. コンフィグレーションの手段:補足1/2 • コンフグレーションの手段が異なっても、結果は同じ – Beanが用意・注入されて、DIコンテナで管理される • コンフグレーションの手段は、ミックスできる 32 DIコンテナ FooService FooDao ID:fooService ID:fooDao XML アノテーション JavaConfig
  33. 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. 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. 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. 36. DIコンテナの作成 • スタンドアロンアプリ(Webアプリじゃないアプリ)実行時 • JUnit実行時 • APサーバ実行時 • Spring Boot実行時 36
  37. 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. 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. 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. 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. 41. まとめ • SpringのDIは、 オブジェクトを用意して注入する部 分を、効率よく柔軟に作成する機能を提供する • コンフィグレーションの手段は3つある – 使い分けが可能 • DIコンテナを作成する方法はケースバイケースでい ろいろある 41
  42. 42. クイズ 42
  43. 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. 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. 実行結果はどうなる? 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. 実行結果はどうなる? 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. 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. 48. さいごに • DIが分かれば、Springの理解力が飛躍的に上がります – Springが提供する様々な機能は、DIの考え方・仕組みで成り立って いる • 裏でやってることがイメージし易い • AOPが分かると、さらに理解力が上がります 48 [改訂新版]Spring入門 Spring徹底入門
  49. 49. 49 ご清聴ありがとうございました
  50. 50. 50 ライセンスについて • JSUGマスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生 作品)の複製・頒布・表示・上演を認めます。 • 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。 • 本作品のライセンスを遵守する限り、派生作品を頒布することを許可します。

×