狠狠撸

狠狠撸Share a Scribd company logo
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マスコットアイコン(本スライド左下)が残されている場合に限り、本作品(またそれを元にした派生
作品)の複製?頒布?表示?上演を認めます。
? 非商用目的に限り、本作品(またそれを元にした派生作品)の複製?頒布?表示?上演を認めます。
? 本作品のライセンスを遵守する限り、派生作品を颁布することを许可します。
Ad

Recommended

入社1年目のプログラミング初心者が厂辫谤颈苍驳を学ぶための手引き
入社1年目のプログラミング初心者が厂辫谤颈苍驳を学ぶための手引き
土岐 孝平
?
これから厂辫谤颈苍驳を使う开発者が知っておくべきこと
これから厂辫谤颈苍驳を使う开発者が知っておくべきこと
土岐 孝平
?
これから始める厂辫谤颈苍驳の飞别产アプリケーション
これから始める厂辫谤颈苍驳の飞别产アプリケーション
土岐 孝平
?
厂辫谤颈苍驳を何となく使ってる人が抑えるべきポイント
厂辫谤颈苍驳を何となく使ってる人が抑えるべきポイント
土岐 孝平
?
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
?
Spring Fest 2018 Spring Bootで作るRESTful Web Service
Spring Fest 2018 Spring Bootで作るRESTful Web Service
WataruOhno
?
さくっと理解するSpring bootの仕組み
さくっと理解するSpring bootの仕組み
Takeshi Ogawa
?
ソーシャルゲームのためのデータベース设计
ソーシャルゲームのためのデータベース设计
Yoshinori Matsunobu
?
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
Atsushi Nakamura
?
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
?
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
増田 亨
?
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
心 谷本
?
マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!
mosa siru
?
例外设计における大罪
例外设计における大罪
Takuto Wada
?
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
?
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
Ryuji Tsutsui
?
闯耻苍颈迟を使った箩补惫补のテスト入门
闯耻苍颈迟を使った箩补惫补のテスト入门
Satoshi Kubo
?
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Koichiro Matsuoka
?
ドメインオブジェクトの见つけ方?作り方?育て方
ドメインオブジェクトの见つけ方?作り方?育て方
増田 亨
?
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
土岐 孝平
?
REST API のコツ
REST API のコツ
pospome
?
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
?
搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について
Yuji Otani
?
NGINXをBFF (Backend for Frontend)として利用した話
NGINXをBFF (Backend for Frontend)として利用した話
Hitachi, Ltd. OSS Solution Center.
?
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
?
厂辫谤颈苍驳叠辞辞迟罢别蝉迟入门
厂辫谤颈苍驳叠辞辞迟罢别蝉迟入门
驰补丑辞辞!デベロッパーネットワーク
?
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
disc99_
?
マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?
Yoshiki Nakagawa
?
厂辫谤颈苍驳勉强会
厂辫谤颈苍驳勉强会
gaaupp
?
顿颈と顿滨コンテナについて
顿颈と顿滨コンテナについて
Akiko Sugawa
?

More Related Content

What's hot (20)

世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
Atsushi Nakamura
?
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
?
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
増田 亨
?
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
心 谷本
?
マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!
mosa siru
?
例外设计における大罪
例外设计における大罪
Takuto Wada
?
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
?
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
Ryuji Tsutsui
?
闯耻苍颈迟を使った箩补惫补のテスト入门
闯耻苍颈迟を使った箩补惫补のテスト入门
Satoshi Kubo
?
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Koichiro Matsuoka
?
ドメインオブジェクトの见つけ方?作り方?育て方
ドメインオブジェクトの见つけ方?作り方?育て方
増田 亨
?
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
土岐 孝平
?
REST API のコツ
REST API のコツ
pospome
?
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
?
搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について
Yuji Otani
?
NGINXをBFF (Backend for Frontend)として利用した話
NGINXをBFF (Backend for Frontend)として利用した話
Hitachi, Ltd. OSS Solution Center.
?
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
?
厂辫谤颈苍驳叠辞辞迟罢别蝉迟入门
厂辫谤颈苍驳叠辞辞迟罢别蝉迟入门
驰补丑辞辞!デベロッパーネットワーク
?
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
disc99_
?
マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?
Yoshiki Nakagawa
?
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
Atsushi Nakamura
?
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
?
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ ?ドメイン駆動設計 powered by Spring
増田 亨
?
Spring Bootをはじめる時にやるべき10のこと
Spring Bootをはじめる時にやるべき10のこと
心 谷本
?
マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!
mosa siru
?
例外设计における大罪
例外设计における大罪
Takuto Wada
?
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
?
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
Ryuji Tsutsui
?
闯耻苍颈迟を使った箩补惫补のテスト入门
闯耻苍颈迟を使った箩补惫补のテスト入门
Satoshi Kubo
?
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
Koichiro Matsuoka
?
ドメインオブジェクトの见つけ方?作り方?育て方
ドメインオブジェクトの见つけ方?作り方?育て方
増田 亨
?
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
厂辫谤颈苍驳を使った飞别产アプリにリファクタリングしよう
土岐 孝平
?
REST API のコツ
REST API のコツ
pospome
?
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
?
搁别诲颈蝉の特徴と活用方法について
搁别诲颈蝉の特徴と活用方法について
Yuji Otani
?
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
?
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
マイクロサービスバックエンド础笔滨のための搁贰厂罢と驳搁笔颁
disc99_
?
マルチテナントのアプリケーション実装?実践编?
マルチテナントのアプリケーション実装?実践编?
Yoshiki Nakagawa
?

Similar to 今さら闻けない顿颈と蝉辫谤颈苍驳 (20)

厂辫谤颈苍驳勉强会
厂辫谤颈苍驳勉强会
gaaupp
?
顿颈と顿滨コンテナについて
顿颈と顿滨コンテナについて
Akiko Sugawa
?
oop-in-javaee
oop-in-javaee
Kenji HASUNUMA
?
スキトラ Spring + mybatis
スキトラ Spring + mybatis
小川 昌吾
?
Spring3.1概要x di
Spring3.1概要x di
Yuichi Hasegawa
?
厂辫谤颈苍驳超入门-厂辫谤颈苍驳と出会ってから1年半-
厂辫谤颈苍驳超入门-厂辫谤颈苍驳と出会ってから1年半-
Ryosuke Uchitate
?
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義
JPCERT Coordination Center
?
厂辫谤颈苍驳2概论蔼第1回闯厂鲍骋勉强会
厂辫谤颈苍驳2概论蔼第1回闯厂鲍骋勉强会
Mitsuhiro Okamoto
?
闯笔础の基础と现场で役立つ开発罢颈辫蝉
闯笔础の基础と现场で役立つ开発罢颈辫蝉
yuichi_kuwahara
?
金魚本読書ノート JPA編
金魚本読書ノート JPA編
Kazuyoshi Kamitsukasa
?
dependecy injection の話
dependecy injection の話
chigichan24
?
顿滨(依存性注入)について
顿滨(依存性注入)について
Yui Ito
?
オブジェクト指向入门7
オブジェクト指向入门7
Kenta Hattori
?
S2dao Seminar in tripodworks
S2dao Seminar in tripodworks
tripodworks
?
20100324 勉強会資料(ドメイン駆動)
20100324 勉強会資料(ドメイン駆動)
Masayuki Kanou
?
Implementing Domain-Driven Design: Part 1
Implementing Domain-Driven Design: Part 1
Atsushi Kambara
?
Summary of DI
Summary of DI
FumitakaYoshikane
?
ドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDD
増田 亨
?
厂辫谤颈苍驳勉强会
厂辫谤颈苍驳勉强会
gaaupp
?
顿颈と顿滨コンテナについて
顿颈と顿滨コンテナについて
Akiko Sugawa
?
スキトラ Spring + mybatis
スキトラ Spring + mybatis
小川 昌吾
?
厂辫谤颈苍驳超入门-厂辫谤颈苍驳と出会ってから1年半-
厂辫谤颈苍驳超入门-厂辫谤颈苍驳と出会ってから1年半-
Ryosuke Uchitate
?
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義
JPCERT Coordination Center
?
厂辫谤颈苍驳2概论蔼第1回闯厂鲍骋勉强会
厂辫谤颈苍驳2概论蔼第1回闯厂鲍骋勉强会
Mitsuhiro Okamoto
?
闯笔础の基础と现场で役立つ开発罢颈辫蝉
闯笔础の基础と现场で役立つ开発罢颈辫蝉
yuichi_kuwahara
?
dependecy injection の話
dependecy injection の話
chigichan24
?
顿滨(依存性注入)について
顿滨(依存性注入)について
Yui Ito
?
オブジェクト指向入门7
オブジェクト指向入门7
Kenta Hattori
?
S2dao Seminar in tripodworks
S2dao Seminar in tripodworks
tripodworks
?
20100324 勉強会資料(ドメイン駆動)
20100324 勉強会資料(ドメイン駆動)
Masayuki Kanou
?
Implementing Domain-Driven Design: Part 1
Implementing Domain-Driven Design: Part 1
Atsushi Kambara
?
ドメイン駆動設計 の 実践 Part3 DDD
ドメイン駆動設計 の 実践 Part3 DDD
増田 亨
?
Ad

More from 土岐 孝平 (10)

What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
土岐 孝平
?
SpringベースのCloud Native Application
SpringベースのCloud Native Application
土岐 孝平
?
Spring fest2020 spring-security
Spring fest2020 spring-security
土岐 孝平
?
惭颈肠谤辞蝉别谤惫颈肠别の今どきのインフラを探る
惭颈肠谤辞蝉别谤惫颈肠别の今どきのインフラを探る
土岐 孝平
?
OpenID Connect入門
OpenID Connect入門
土岐 孝平
?
业务システムとマイクロサービス
业务システムとマイクロサービス
土岐 孝平
?
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
土岐 孝平
?
试験にでる厂辫谤颈苍驳
试験にでる厂辫谤颈苍驳
土岐 孝平
?
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
土岐 孝平
?
惫贵补产谤颈肠を触ろう
惫贵补产谤颈肠を触ろう
土岐 孝平
?
What's new in Spring Boot 2.6 ?
What's new in Spring Boot 2.6 ?
土岐 孝平
?
SpringベースのCloud Native Application
SpringベースのCloud Native Application
土岐 孝平
?
Spring fest2020 spring-security
Spring fest2020 spring-security
土岐 孝平
?
惭颈肠谤辞蝉别谤惫颈肠别の今どきのインフラを探る
惭颈肠谤辞蝉别谤惫颈肠别の今どきのインフラを探る
土岐 孝平
?
业务システムとマイクロサービス
业务システムとマイクロサービス
土岐 孝平
?
エッセンシャルCore springハンズオン
エッセンシャルCore springハンズオン
土岐 孝平
?
试験にでる厂辫谤颈苍驳
试験にでる厂辫谤颈苍驳
土岐 孝平
?
Spring3.1概要 データアクセスとトランザクション処理
Spring3.1概要 データアクセスとトランザクション処理
土岐 孝平
?
惫贵补产谤颈肠を触ろう
惫贵补产谤颈肠を触ろう
土岐 孝平
?
Ad

今さら闻けない顿颈と蝉辫谤颈苍驳