SlideShare a Scribd company logo
1 of 50
Download to read offline
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 オブジェクトB
使う(メソッド呼出)
※「具象クラスへの依存」という解釈もあります
依存するオブジェクトの作成
• 依存するオブジェクトを「使う」には、依存するオブジ
ェクトを「用意する」必要がある。
6
オブジェクトA オブジェクトB
使う(メソッド呼出)
「使う」ためには、
「用意する」必要が
ある。
「用意する」とは?
・newで具象クラスのオブジェクトを生成する
・オブジェクトの初期設定や初期処理を行う
サンプルプログラム
• DAO(データアクセスオブジェクト)がデータソースを「使う」
– データソースを使って、コネクションプールしておいたコネクションを取
得する(getConnectionメソッドを呼出す)
7
FooDao
データソースgetConnection
DB
「使う」ためには、
「用意する」必要が
ある。
「用意する」とは?
・newで具象クラスのオブジェク
トを生成する
・接続先やプール数を設定する
≪interface≫
DataSource
getConnection
DataSourceA
getConnection
DataSourceB
getConnection
FooDao
getFoo
使う
依存するオブジェクトを用意する方法
• その①:使う側が自分で用意する
• その②:使う側とは別のところで用意する
8
その①:使う側が自分で用意する
• 使う側のプログラムが長くなる
– 本質ではない処理が入り込む
• 依存するオブジェクトの設定を変更したり、具象クラスを変更する場合は
、使う側のプログラムを修正する必要がある
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
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
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
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();
・・・
「用意する」
部分
修正不要 「用意する」部分を
変更
DIとは?
• (依存するオブジェクトを)「用意する」部分と「使う」
部分を分離するためのテクニック(考え方)
• 依存するオブジェクトを、使う側のオブジェクトとは「
別のところ」で作成してもらって、参照を設定(注入)
してもらう
13
使う側
依存する
オブジェクト
使う
別のところ
①用意する②設定(注入)する
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();
・・・ 「注入する」部分
WebアプリケーションとDI
• WebアプリケーションのオブジェクトとDIの例
15
Controller Service Dao データソース
別のところ
①用意する
②用意する・注入する
③用意する・注入する
④用意する・注入する
使う使う 使う
• 使う側のテストが容易
– 例:Serviceをテストする際に、MockのDaoのオブジェクトを注入して
テストする
Service Dao(Mock)
別のところ
(テスト用)
使う
用意する注入する
DB
DIとシングルトン
• DIの仕組みだとシングルトン(あるクラスのひとつのオブジェ
クトを使いまわすこと)が容易
– コネクションプールのような共有すべきデータを共有できる
– 不必要なオブジェクトの生成を避ける
16
XxxDao
YyyDao
ZzzDao
データソース
別のところ
使う
使う
使う
②注入する
③注入する
④注入する
①用意する
シングルトン
留意点
• すべてのオブジェクトを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;
}
メソッド呼出の度に作成するオブ
ジェクト
まとめ
• DIとは、(依存するオブジェクトを)「用意する」部分と
「使う」部分を分離するためのテクニック(考え方)
– 依存するオブジェクトを、使う側のオブジェクトとは「別のと
ころ」で用意してもらって、注入してもらう
– 依存するオブジェクトを変更する際に、使う側のプログラ
ムを修正する必要が無い
• すべてのオブジェクトをDIする訳ではない
18
クイズ
19
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);
}
}
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の場合、取得するのはなく、
「注入」してもらいます。
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);
}
}
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);
}
}
答え:適用しています
依存するオブジェクトを、
自分で用意してないし、
取得もしていません。
「注入」してもらってます。
第2部
SpringのDIを理解しよう
24
SpringのDI
• Springは、「別のところ」を効率よく柔軟に作成する
機能を提供する
25
使う側
依存する
オブジェクト
使う
別のところ
①用意する②設定(注入)する
Springが機能を
提供
Springの用語
• Bean
– SpringのDIで作られたオブジェクトのこと
• コンフィグレーション
– Beanの定義情報。どのクラスのBeanを用意するか?どのBeanを注入する
か?などを定義する
• DIコンテナ
– Beanの入れ物。コンフィグレーションに従ってBeanを作成し、IDを割り振って
管理する。IDや型を指定してBeanを取得することも可能。
26
DIコンテナ
コンフィグレー
ション Bean Bean
ID:foo ID:bar
コンフィグレーションの手段
• XML
• JavaConfig
• アノテーション
27
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);
・・・
}
}
【参考】実行の例
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
アノテーション
• 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
ステレオタイプアノテーション
• コンポーネントスキャンでBeanを用意する際の目印
となる
• @Componentをベースにして、複数の種類がある
– Beanの役割に応じて使い分ける
– Beanを用意する以外に、若干の付加機能が付く
31
@Controller
@Component
@Service @Repository @Configration
コンフィグレーションの手段:補足1/2
• コンフグレーションの手段が異なっても、結果は同じ
– Beanが用意・注入されて、DIコンテナで管理される
• コンフグレーションの手段は、ミックスできる
32
DIコンテナ
FooService FooDao
ID:fooService ID:fooDao
XML
アノテーション
JavaConfig
コンフィグレーションの手段:補足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
コンフィグレーションの手段の使い分け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
・・・ ・・・
コンフィグレーションの手段の使い分け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
DIコンテナの作成
• スタンドアロンアプリ(Webアプリじゃないアプリ)実行時
• JUnit実行時
• APサーバ実行時
• Spring Boot実行時
36
スタンドアロンアプリ実行時
• 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();
・・・
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);
}
}より簡潔な書き方
APサーバ実行時
39
web.xml
・・・
AppConfig.class
・・・
Springが提供するServlet
やListenerを登録する際に、
コンフィグレーションのファ
イルを指定できる
Tomcat
DIコンテナ
Controller Service Dao DataSource
SpringのServletやListener
がDIコンテナを作成する
ブラウザ
/showFoo
Tomcat起動後は、DIコンテナ
が作成済みなので、
Controllerにアクセスできる
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
まとめ
• SpringのDIは、 オブジェクトを用意して注入する部
分を、効率よく柔軟に作成する機能を提供する
• コンフィグレーションの手段は3つある
– 使い分けが可能
• DIコンテナを作成する方法はケースバイケースでい
ろいろある
41
クイズ
42
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
【問題】
以下のコードと等しい記述はどれでしょう?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
@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
@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つ存在するため、どれを
注入すればよいか分から
ない
Bean IDを指定して@Autowireが可能
47
package sample;
@Service
public class FooService {
@Autowired
@Qualifier("fooDaoA")
private FooDao fooDao;
public void execute() {
fooDao.foo();
}
}
@QualifierでBean IDを指
定できる
さいごに
• DIが分かれば、Springの理解力が飛躍的に上がります
– Springが提供する様々な機能は、DIの考え方・仕組みで成り立って
いる
• 裏でやってることがイメージし易い
• AOPが分かると、さらに理解力が上がります
48
[改訂新版]Spring入門 Spring徹底入門
49
ご清聴ありがとうございました
50
ライセンスについて
• JSUGマスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生
作品)の複製・頒布・表示・上演を認めます。
• 非商用目的に限り、本作品(またそれを元にした派生作品)の複製・頒布・表示・上演を認めます。
• 本作品のライセンスを遵守する限り、派生作品を頒布することを許可します。

More Related Content

What's hot

Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門
Satoshi Kubo
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 

What's hot (20)

Spring超入門-Springと出会ってから1年半-
Spring超入門-Springと出会ってから1年半-Spring超入門-Springと出会ってから1年半-
Spring超入門-Springと出会ってから1年半-
 
RESTfulとは
RESTfulとはRESTfulとは
RESTfulとは
 
Springを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしようSpringを使ったwebアプリにリファクタリングしよう
Springを使ったwebアプリにリファクタリングしよう
 
Spring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作るSpring Boot × Vue.jsでSPAを作る
Spring Boot × Vue.jsでSPAを作る
 
Spring fest2020 spring-security
Spring fest2020 spring-securitySpring fest2020 spring-security
Spring fest2020 spring-security
 
こんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツールこんなに使える!今どきのAPIドキュメンテーションツール
こんなに使える!今どきのAPIドキュメンテーションツール
 
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のことSpring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
 
Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門Junitを使ったjavaのテスト入門
Junitを使ったjavaのテスト入門
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
 
Spring と TDD
Spring と TDDSpring と TDD
Spring と TDD
 
Mavenの真実とウソ
Mavenの真実とウソMavenの真実とウソ
Mavenの真実とウソ
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
 
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptxネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
 
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
初めてでも30分で分かるSpring 5 & Spring Boot 2オーバービュー
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
はじめての datadog
はじめての datadogはじめての datadog
はじめての datadog
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web ServiceSpring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 

Similar to 今さら聞けないDiとspring

2010 icse-an analysis of the variability in forty preprocessor-based software...
2010 icse-an analysis of the variability in forty preprocessor-based software...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
 
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.124時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
聡 中川
 
DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃
Teruo Adachi
 

Similar to 今さら聞けないDiとspring (15)

Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
 
Androidで学ぶ
Androidで学ぶAndroidで学ぶ
Androidで学ぶ
 
iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜iPhoneアプリ開発の歩き方〜Swift編〜
iPhoneアプリ開発の歩き方〜Swift編〜
 
Tokyo r30 beginner
Tokyo r30 beginnerTokyo r30 beginner
Tokyo r30 beginner
 
2013講義1
2013講義12013講義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...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 training4desinger
第一回Android training4desinger
 
AndroidでDIxAOP
AndroidでDIxAOPAndroidでDIxAOP
AndroidでDIxAOP
 
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.124時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
24時間でiOSアプリ-Twitterクライアント-の作成にチャレンジ ver1.1
 
Teclab3
Teclab3Teclab3
Teclab3
 
Tokyo r38
Tokyo r38Tokyo r38
Tokyo r38
 
動的なILの生成と編集
動的なILの生成と編集動的なILの生成と編集
動的なILの生成と編集
 
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティスJsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
Jsug2015 summer spring適用におけるバッドノウハウとベタープラクティス
 
OpenStack Swift紹介
OpenStack Swift紹介OpenStack Swift紹介
OpenStack Swift紹介
 
DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃DevOpsが引き金となるインフラエンジニアの進撃
DevOpsが引き金となるインフラエンジニアの進撃
 

More from 土岐 孝平

Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
土岐 孝平
 

More from 土岐 孝平 (8)

What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
 
SpringベースのCloud Native Application
SpringベースのCloud Native ApplicationSpringベースのCloud Native Application
SpringベースのCloud Native Application
 
Microserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探るMicroserviceの今どきのインフラを探る
Microserviceの今どきのインフラを探る
 
OpenID Connect入門
OpenID Connect入門OpenID Connect入門
OpenID Connect入門
 
業務システムとマイクロサービス
業務システムとマイクロサービス業務システムとマイクロサービス
業務システムとマイクロサービス
 
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオンエッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
 
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
 
vFabricを触ろう
vFabricを触ろうvFabricを触ろう
vFabricを触ろう
 

今さら聞けないDiとspring