20210620のJavaに関する記事は6件です。

双方向性マップ

この記事では、Androidで双方向性マップを使う方法について記載しています。(Javaでも使えます) 双方向性マップ 双方向性マップは、「keyを指定してvalueを取得する」だけでなく、「valueを指定してkeyを取得する」ことが出来ます。 使い方 双方向性マップのライブラリはいくつかあるようですが、ここではcom.google.guavaのBiMapを使います。 ライブラリは、MavenまたはGradleで依存関係を指定することで使用できます。 dependencies { implementation("com.google.guava:guava:30.1.1-android") // Javaの場合は 30.1.1-jre } 「valueを指定してkeyを取得する」場合は、inverseメソッドをコールすることで、keyとvalueが反転したMapが取得できます。 val userId: BiMap<Int, String> = HashBiMap.create() userId.put(1, "Taro") // keyとvalueが反転したMapを取得 val index = userId.inverse()["Taro"] 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Web/まとめ] JUnit5 で Mockitoを利用する方法

背景 現在、担当中のjava moduleで Spring 2.3系から Spring2.5へmigrationを行なっている。 その際に、test周り、特にmockitoの移行で若干ハマったのでメモ。 特に、以下の英語LINKがよくまとまっていたので、この内容を元に要約してみる。 https://mincong.io/2020/04/19/mockito-junit5/ なお、自分のMockito + Spring boot test frameworkの知識補充のために記載しているので、WEB Pageの丸翻訳というわけではなく、自分なりの理解や補足を加筆している。 なので、LINKの中で初めて知ること、わからないメソッドなどは適宜調べて自分なりのオリジナルまとめとなっている。 Junit5で Mockitoを利用する方法 以下の3つの方法があり、各方法での実装例や方法だけではなく、メリデメについてもリストしていく。 MockitoExtension MockitoAnnotations#initMocks Mockito#mock 実装の前に、、、 Mockitoそのものを利用するために、以下のDependencyをプロジェクト/モジュールの pom.xml などに追加する必要がある。 追加例 (versionは適宜最新のものにUpdateすること): <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.28.2</version> <scope>test</scope> </dependency> 注意 もし、Spring bootのstarter moduleを利用している場合、特に spring-boot-starter-test が test dependencyとして追加されている場合は、上記モジュールはすでに依存関係に追加されているので、明示的に追加しなくてもビルドパスに追加される。 例: pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 上記dependencyが追加されている状態で、mvn dependency:treeなどを実行してみると、、、。 添付のように spring-boot-starter-test からの依存として、mockito-coreがモジュールのテストライブラリとして自動的に追加されていることがわかる。 なので、Spring boot testを利用している場合は、明示的にインポートを行う必要はない! 方法1. MockitoExtension 概要 JUnit5で新規追加されたExtention APIを用い、Mockito用のExtentionを @ExtendWith を使い、組み込む @Mock アノテーションを使い、Mockオブジェクトを定義する 実装例 @ExtendWith(MockitoExtension.class) class BookReaderAnnotationWithExtensionTest { @Mock private Book mockedBook; private BookReader reader; @BeforeEach void setUp() { reader = new BookReader(mockedBook); } @Test void testGetContent() { Mockito.when(mockedBook.getContent()).thenReturn("Mockito"); assertEquals("Mockito", reader.getContent()); } } (補足) JUnit5 Extention API & JUnit4 Runnerからの移行 JUnit4では、Mockito(特に @Mockアノテーション)を利用する場合には、Runnerなどの拡張実装を利用する必要があった。 が、JUnit5からはExtention APIを利用することになるため、@Extention を代わりに利用する必要がある。 JUnit4のRunnerに関しては、以下のLINKを読んでざっと理解した。 https://qiita.com/YutaKase6/items/1f3ca15900b5146351de - Mockitoの @Mock アノテーションを利用するためには MockitoJUnitRunner を指定しなければならない また、Junit4 Runner から Junit5 Extentionへの移行に関しては、以下のLINKで概要を理解。 https://www.m3tech.blog/entry/2018/12/20/junit5 テストの拡張機能 JUnit4ではテストの事前処理や事後処理などを汎用的に実装するための機能として、@RunWithや@Ruleなどのテスト拡張機能がありました。 JUnit5では、これらのテスト拡張機能が廃止され、@ExtendWithに置き換わっています。 @RunWithは、1クラスに1つしか指定できなかったため、複数の拡張を同時に使用することができませんでした。そのため、Springのための@RunWith(SpringRunner.class)を使うと@RunWith(Parameterized.class)が使えないなど、便利な機能を上手く活かしずらいことがありました。 @ExtendWithは同じクラスに複数指定することができ、この手の問題が解消されました。 また、同英語記事内では、上記引用と同じポイントについても述べている (MockitoExtensionを利用した場合の特徴 => 複数のExtentionを指定することができる を参考)。 MockitoExtensionを利用した場合の特徴 & Point Point1. 複数のExtentionを指定することができる JUnit4では Runnerは 1つのみ指定可能、複数指定不可 である一方、Junit5 Extentionからは 複数指定が可能となり、複数のExtentionをTest classへ追加することができるようになった (そしてこれは便利 とも)。 Point2. MockitoAnnotations#initMocks(Object) を呼ばすとも、@Mock の自動初期化が可能 各 @Mock をテストケースごとに登録したStub挙動をリセットさせる必要がある。通常は、MockitoAnnotations#initMocks(Object) メソッドを @BeforeEach 内などで実行する必要がある。 が、MockitoExtensionを利用すると、暗黙的に実行してくれる。 MockitoAnnotations.initMocks(this)については、当ページのMock作成の方法2でも再度説明する Point3. 実装とは関係のない余計なStub定義がないか自動で検知をしてくれる 詳細は Mockito#validateMockitoUsage()のJavaDoc を参照せよとのこと。 どういうことかというと、上記の実装例で見てみると、 もし以下のテストロジックで、 実際にテストするメソッド reader.getContent() 内で  Mockito.when で定義した mockedBook.getContent() 実は全然呼ばれていなかったとする @Test void testGetContent() { Mockito.when(mockedBook.getContent()).thenReturn("Mockito"); assertEquals("Mockito", reader.getContent()); verify(mockedBook, times(1)).getContent(); } すると、mockitoは、以下のようなエラーをthrowしてくれる。 -> at …testGetContent(BookReaderAnnotationWithExtensionTest.java:38)) Please remove unnecessary stubbings or use ‘lenient’ strictness. More info: javadoc for UnnecessaryStubbingException class.” そうすることで各テストケース内で必要最低限のStub実装のみが定義されていることが保証され、テストコードがneatかつ読みやすくなる ちなみに、この辺、自分は結構きちんと理解しにくかったので、別Quita Page にサンプル実装例をつけてまとめた。 詳細は、以下のLINKも参照した。 https://qiita.com/kazuki43zoo/items/8762927ed182878eb58c (lenient モードに設定するなどして、このエラーをinactiveにすることができるらしい) Point4. 利用のために、別途ライブラリを追加でビルドパスへ追加する必要がある 以下のDependencyを pom.xml などへ追加する必要がある。 追加例(versionは適宜最新のものにUpdateすること): <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>2.28.2</version> <scope>test</scope> </dependency> 注意 mockito-core と同じで、もし Spring test frameworkを利用している場合は、デフォルトでDependencyとして上記モジュールは追加されているので、何もしなくてもよし もし、Spring bootのstarter moduleを利用している場合、特に spring-boot-starter-test が test dependencyとして追加されている場合は、上記モジュールはすでに依存関係に追加されているので、明示的に追加しなくてもビルドパスに追加される。 例: pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> 上記dependencyが追加されている状態で、mvn dependency:treeなどを実行してみると、、、。 添付のように spring-boot-starter-test からの依存として、mockito-coreがモジュールのテストライブラリとして自動的に追加されていることがわかる。 なので、Spring boot testを利用している場合は、明示的にインポートを行う必要はない! Junit5 Extention APIでのPros&Consまとめ Pros mockの手動初期化が必要ない (MockitoAnnotations#initMocks(Object) がいらない) Stubのverifyが正しく行われているかチェックしてくれる @Mock アノテーションを mock変数に追加させることで、どの変数がmockなのかがとてもわかりやすくなる Mockを簡単に作成し、簡単に利用することができる @ExtendWith が複数指定可能なので、他の任意のExtentionも併用することができるため、便利 Cons org.mockito:mockito-junit-jupiter ライブラリを別途追加しなければならない ただし、上記 注意 にも記載した通り、Spring boot frameworkを使っている場合はその心配をする必要はない (自動的に依存ライブラリとして透過的に組み込まれるため) 方法2. MockitoAnnotations.initMocks 概要 @MockアノテーションでMockオブジェクトを作成する 各テストケース実行前に MockitoAnnotations#initMocks(Object)メソッドを手動で実行し、Mock objectの初期化を行う 上記 方法1. MockitoExtention で説明した通り、手動でinitMocksをコールするため、 MockitoExtentionは使わない 実装例 // you don't need: @ExtendWith(MockitoExtension.class) class BookReaderAnnotationWithSetupTest { private BookReader reader; @Mock private Book mockedBook; @BeforeEach void setUp() { MockitoAnnotations.initMocks(this); reader = new BookReader(mockedBook); } @Test void testPrintContent() { mockedBook.printContent(); Mockito.verify(mockedBook).printContent(); } @Test void testGetContent() { Mockito.when(mockedBook.getContent()).thenReturn("Mockito"); assertEquals("Mockito", reader.getContent()); } } ちなみに、MockitoのJavaDoc での実装例の記載しておく。 親クラス SampleBaseTestCase で MockitoAnnotations.initMocks(this) が毎テストケース実行前にコールされていることがわかる。 public class ArticleManagerTest extends SampleBaseTestCase { @Mock private ArticleCalculator calculator; @Mock(name = "database") private ArticleDatabase dbMock; @Mock(answer = RETURNS_MOCKS) private UserProvider userProvider; @Mock(extraInterfaces = {Queue.class, Observer.class}) private articleMonitor; private ArticleManager manager; @Before public void setup() { manager = new ArticleManager(userProvider, database, calculator, articleMonitor); } } public class SampleBaseTestCase { @Before public void initMocks() { MockitoAnnotations.initMocks(this); } } MockitoAnnotations.initMocks を利用した場合の特徴 & Point Point1. @Mockを利用することでコードが読みやすくなる + Mock Objectの初期化が簡単 上記initMocksに関するJavaDocの以下テキストより、、 MockitoAnnotations.initMocks(this); initializes fields annotated with Mockito annotations. Allows shorthand creation of objects required for testing. Minimizes repetitive mock creation code. Makes the test class more readable. Makes the verification error easier to read because field name is used to identify the mock. 以下のメリットがあることがわかる。 Mockオブジェクトが簡単に初期化&生成できる Mock作成の手動コードを省略することができる ( initMocks(this)が全てやってくれるので) テストコードが読みやすい -@Mockがマーキングの様な役目を果たしてくれるので、開発者は一見でどのオブジェクトがMockなのかがすぐにわかる (そうではないと、どこかで mock()みたいなメソッドをコールしているか探して判別しなければならず、面倒) Mockがクラスのインスタンス変数として定義されているので、mockのverification errorなどが発生した時のトラブルシューティング/デバッグが楽 ちなみに 方法1. MockitoExtention では、すでに上記メリットを兼ね備えた上に、initMocksメソッド自体を手動で呼ぶ必要がなくなるので、方法1. MockitoExtentionの方がさらに洗練された実装となっていることがわかる 上記を踏まえて、Pros & Consをまとめてみると、、 Pros @Mock アノテーションを mock変数に追加させることで、どの変数がmockなのかがとてもわかりやすくなる Mockを簡単に作成し、簡単に利用することができる Cons 方法1. MockitoExtention と比べて、Stubのverifyが正しく行われているかチェックまでしてくれない 方法3. Mockito.mock 概要 Extention APIや Mockito frameworkに頼らず、全て手動でコードする Mockito#mock(Class<T> classToMock) メソッドを任意のコードで呼ぶことで mock objectを作成する サッと紹介されて一番面倒臭そう + お勧めではないな実装には見えるが、テストが非同期で実行される場合は、このオプションは有用だと思う 実装例 class BookReaderClassicMockTest { private BookReader reader; private Book mockedBook; @BeforeEach void setUp() { mockedBook = Mockito.mock(Book.class); reader = new BookReader(mockedBook); } @Test void testPrintContent() { mockedBook.printContent(); Mockito.verify(mockedBook).printContent(); } @Test void testGetContent() { Mockito.when(mockedBook.getContent()).thenReturn("Mockito"); assertEquals("Mockito", reader.getContent()); } } Mockito.mock を利用した場合の特徴 & Point Point1. 非同期テスト実行に強い 方法1. MockitoExteption と 方法2. MockitoAnnotations.initMocks では、共に以下の共通点がある。 @Mockアノテーションを使い、 インスタンス変数としてMockオブジェクトを定義する つまり、各テストケースがマルチスレッドでインスタンス変数として定義されたMockオブジェクトを共有し、使い回すことになったらどうするのだろう。。。 JUnitは基本デフォルトでは、スレッドセーフ、同期実行であるものの、もし複数テストケースを(ビルド時間の軽減などのために)非同期で実行したらどうなるのだろう?? ちなみに、私は、テストはいつでも非同期実行に対応すべきよう実装するべきものと考えている。 例えば、JSにおけるJESTなどは非同期実行がデフォルトである、またこのstackoverflow linkの意見に大大大賛成 である) But don't forget that: Good automated tests should be independent, isolated and reproducible, making them ideal candidates for being run concurrently. なので、気になって調べてみたところ、以下のLINKが役立った。 https://stackoverflow.com/questions/59651296/are-java-mockito-mocked-method-invocations-thread-safe https://github.com/mockito/mockito/wiki/FAQ#is-mockito-thread-safe まとめると Mockitoで作成されたMock Objectが概してMulti threadに問題なく対応できるように実装されている が、複数Threadが一つのMock Objectを共有し、使いまわしており、さらにそのMock objectに対して verifyをかけて、各Thread内で検証を行おうとする場合は、正しく動作しない そのような実装では、以下の問題が発生する可能性がある そもそもテストとして正しい実装方法ではない (Single Threadに対して、特定のMock Objectが作成されるべきであり、複数のThreadでシェアされるべきものではない) 複数のスレッドから共有されたMock Objectが各スレッドごとに変わるようなMock挙動を定義され、それに対してassertionを行うような場合、Mockは期待された挙動をせず、ランダムな挙動をするかもしれない WrongTypeOfReturnValue みたいなExceptionがthrowされるかもしれない なので、私の懸念はドンピシャで、方法1. MockitoExtention & 方法2. MockitoAnnotations.initMocks はマルチスレッドで並列実行されるテストの場合には、正しく動作することができないはず。 そして、その時の救世主となるのが、この方法での実装である!! 例えば、テストケース内のローカル変数としてmockを定義すれば、そのMock objectはスレッドセーフとなり、安全にテストを実行することができる。 ただ、当然、例の通り、コードがrepeatable/冗長化してしまうことがわかるが。。 スレッドセーフにしたテスト実装例: class BookReaderClassicMockThreadSafeTest { @Test void testPrintContent() { Book mockedBook = Mockito.mock(Book.class); BookReader reader = new BookReader(mockedBook); mockedBook.printContent(); Mockito.verify(mockedBook).printContent(); } @Test void testGetContent() { Book mockedBook = Mockito.mock(Book.class); BookReader reader = new BookReader(mockedBook); Mockito.when(mockedBook.getContent()).thenReturn("Mockito"); assertEquals("Mockito", reader.getContent()); } } 上記を踏まえて、Pros & Consをまとめてみると、、 Pros Mock Object作成をフレームワークに依存しないので、Mock Objectのコントロールをより実装者が管理できる 例えば、上記に示したようにスレッドセーフにするため常にローカル変数で定義するとか。。 Mock Objectをインスタンス変数以外として好きなように定義する 例えば、上記に示したようにスレッドセーフにするため常にローカル変数で定義するとか。。 Cons コードが冗長になる Mock Objectをクリーンかつ読みやすく定義できない 方法1 & 方法2 では @Mock アノテーションを使い Mock Objectとしてマーキングもできた 方法1. MockitoExtention と比べて、Stubのverifyが正しく行われているかチェックまでしてくれない 会社のプロジェクトではどれを使うか。。。 とても悩むところではあるが、うちの会社の事情を考えると、(IT系スタートアアップとか、IT設備やCI/CDに力入れて潤沢にマシンリソースが使える会社は違うんだろうなぁ。。。と思いつつ。。。 ) Build CI/CDで Jenkinsを使っているものの、割り当てられてメモリやマシンリソースが少ない 可能な限りスレッドを発生させるなと言われ、mockserverも各テストケースごとではなく、テストクラスごとに起動させるよう言われた (そうでないと、 java.lang.OutOfMemoryError: unable to create new native thread. が頻発しちゃった) なので、(Java/Spring boot projectに関しては)テストを非同期で行うよう拡張することは今現在、あまり考えられにくい。。 上記事情から考えると、 テストは同期/シングルスレッド/シーケンシャルに実行する前提で進める すると、 方法3. Mockito.mock はテストコードの冗長化を促進するだけであまりメリットはない とすると、方法1. MockitoExtentionを利用し、かつ github issue とソースコードコメントなどに、非同期環境での実装は対応していないとドキュメントする方法が一番良いのではないか? 非同期に対応していない、ということは絶対にどこかへ記録しておいた方が良いはず
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

開発プロセスとSpringBootについて

Java第3回 自分用のメモです。 Webアプリケーションとは ブラウザ上で利用できるアプリケーション HTML/CSSやTCP/IPの基礎やブラウザの挙動なども理解する必要もある これら全てできるエンジニアのことをフルスタックエンジニアと呼ぶ Webアプリケーションでよく使う用語 クライアントとサーバー * クラサバ構成はクライアントがブラウザからアプリケーションを起動し,サーバーが要求を受け付け,プログラムを起動し, その結果をクライアントに返す * C#,VB.netがよく使われる リクエストとレスポンス クライアントからサーバへHTTPリクエストを送る サーバはそのリクエストに対して処理をした結果をレスポンスとしてクライアントへ送る API(WebAPI)があり,部品として使用することができる.これもリクエストを送るという意味で使うが「叩く」ともいう. アプリケーションサーバからブラウザに返すというのがレスポンスの仕組み 通信 Uniform Resource Identifier, Uniform Resource Locator, Uniform Resource Name ブラウザからWebアプリケーションを動かす場合はURLが必要 URLはサーバー提供者がどこにいるかを示すURIの一部 URIはURLの他にURNを含む URNは名前を特定する,URLは場所を特定する こうしたリクエストとレスポンスのやりとりを通信という 動的な処理をする→webアプリケーション 静的な処理しかしない→webサイト HTTP 主にGET,POST,RESTAPIでが使われる GETは情報を取得したい時に利用 POSTは情報の登録や更新を行いたいときに利用 GETにはクエリパラメータがある(URLの?q=の部分) POSTはリクエストボディにつくが気にしなくても良い HTML HTML5はHyper Text Markup Languageすなわち文書に印をつけるだけでプログラミング言語ではなくマークアップ言語である CSS3はHTMLで書かれたものを飾り付けする JSはプログラミング言語である.ブラウザ上でアニメーション表現やHTMLの組み替えなどの銅的な処理を扱う JSはjQuery,Angular,React,Vueをライブラリに持つ.jQueryは重要 開発の流れ 要求分析→要件定義→基本設計→詳細設計→コーディング→コードレビュー→単体テスト→結合テスト→システムテスト→受け入れテスト これが基本的な開発の流れ(V字モデル) ##開発プロセス ウォーターフォール 工程を水のように表した方式で,上流から下流へ一方方向へ進む.下流で発見した問題を上流まで戻って修復することが難しい スクラム
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java用語集

①クラス プログラム実行に必要な処理をまとめた設計図 ②メソッド いくつかの処理をひとまとめにしたもの  インスタンスメソッド インスタンスに紐づけられたメソッド インスタンス固有の振る舞いを表す  クラスメソッド クラスに紐づけられたメソッド クラス全体の固有の振る舞いを表す  ※車クラスがあった場合に、インスタンスメソッドは1台の車インスタンスごとの振る舞いを表すのに対し、クラスメソッドは車全体の振る舞い。 ③引数 メソッドに渡す値 入力値 ④戻り値 返ってくる値 出力値 ※和を計算するメソッドを作成した場合、数値が引数、和が戻り値 ⑤変数 データを一時的に格納する箱   ⑥データ型 取り扱うことができるデータのタイプ ⑦整数型 (byte型、short型、int型、long型) ⑧浮動小数点数型(double型、float型) ⑨文字型(char型) ⑩論理型(boolean型) ⑪インターフェース クラスに含まれるメソッドの具体的な処理内容を記述せず、変数とメソッドの型のみを定義したもの ⑫インスタンス クラスから作られるオブジェクト(実体) ⑬文字列 複数の文字で構成される文字列を扱うときは、Stringクラスを利用 ⑭配列 複数の値をまとめて扱うことができる機能 ⑮コンパイル プログラムをコンピューターが実行できる形に翻訳すること ⑯演算子 データ処理の基礎となる重要な手続き  算術演算子 「+」(足し算) 「-」(引き算)「」(かけ算) 「/」(割り算) 「%」(余り)    代入演算子 「=」「+=」「a += b」とすると、「a = a + b」  「-=」 「=」「a *= b」とすると、「a = a * b」        「/=」 「%=」「a %= b」とすると、「a = a % b」    比較演算子 「==」「x == y」とした場合、xとyが等しいときにtrue、そうでないときにfalse返す。        「<」「x < y」とした場合、xがyよりも小さいときにtrue、そうでないときにfalseを返す。        「>」「x > y」とした場合、xがyよりも大きいときにtrue、そうでないときにfalseを返す。        「 <=」「x <= y」とした場合、xがyよりも小さいか等しいときにtrue、そうでないときにfalseを返す。        「 >=」「x >= y」とした場合、xがyよりも大きいか等しいときにtrue、そうでないときにfalseを返す。        「!=」「x != y」とした場合、xとyが等しくないときにtrue、等しいときにfalseを返す。 ⑰制御文 基本構造である「順次」「選択」「反復」といった処理を実現するための構文 if文 条件分岐を行うため for文 処理を決まった回数繰り返す際に利用 while文 条件式を満たす間、処理をループさせるための構文 break文 for文やwhile文のループ処理中にbreak文が読み込まれると、処理を中断 continue文 for文やwhile文のループ処理中にcontinue文が読み込まれると、現在実行している処理を終了し、次のループ処理に移る。 switch文 多分岐処理をさせるときに便利な構文 ⑱条件分岐 与えられた条件の真偽に応じて実行する処理を変えること ⑲オブジェクト 設計図に基づいて作られた自動車(例)クラスを実体化(インスタンス化)したもの ⑳オブジェクト指向 オブジェクトを部品のように組み合わせてシステムを構築する考え方 ㉑継承 あるクラスのフィールドやメソッドを引き継いで、新しいクラスを定義すること  スーパークラス 継承を行う際、継承元となるクラス  サブクラス  継承先となるクラス ㉒オーバーライド       
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ラムダ式を使った配列の実験(Java編)

ラムダ式を使った配列の実験(Java編)です。 package nogizaka // ラムダ式の実験プログラム // 2021/6/20 新規作成 // Author 乃木坂好きのITエンジニア import java.util.ArrayList; import java.util.Arrays; import java.util.List; //ラムダ式実験プログラム public class hairetsu_test { public static void main(String[] args) { //配列 List<Integer> data = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12)); //ラムダ式で3で割り切れない数字を要素から削除する data.removeIf( (Integer i) -> { return i % 3 !=0; } ); System.out.println(data); } } 勉強をかねてラムダ式を使ってプログラムを作りました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SpringBoot のアノテーションについてのメモ

最近勉強を始めたフレームワークなので、お勉強がてら色々書いてみました。 そのうち何かこいつを使って試作してみたいですね。 DI について @Autowired 一部の変数宣言に@Autowired を付与すると、DI の対象クラス(コンポーネントクラス)を探し、その変数にコンポーネントクラスのインスタンスを割り当ててくれます。 以下のクラスが対象です。 @Component @Controller @Service @Repository @Configuration @RestController @ControllerAdvice @ManagedBean @Named @Mapper @Bean DI の対象ではないクラス(上記アノテーションが割り当てられていないクラス)のメンバに対して@Autowired を指定すると実行時エラーが出ます。 @Scope このアノテーションに引数を指定してクラスに付与すると、そのクラスのライフサイクルを指定することができます。 指定できる引数は以下の通りです。 スコープ 概要 singleton Spring 起動時に一つだけインスタンスが生成される。二つ以上は生成されないので、アプリ全体でこの一つのインスタンスが共有される。@Scope を付与しなかった場合はsingleton になる。singleton のクラスのメンバ変数として、singleton 以外のライフサイクル管理のインスタンス(session等)を持たせてはいけない。Spring 起動中singleton のクラスから参照され続けるため、@Scope 指定したライフサイクル通りに寿命管理されなくなる。 prototype 対象クラスのインスタンスを取得するタイミングで都度インスタンスが生成される。 session HTTP のセッションが始まってから終わるまでがインスタンスの寿命になる。 request HTTP リクエスト処理を始めてから終わるまでがインスタンスの寿命になる。 globalSession ポートレット環境でのGrobalSession が始まってから終わるまでがインスタンスの寿命になる。 application サーブレットのコンテキストの寿命にインスタンスの寿命が合わせられる。 // サンプルコード @Controller @Scope("request") public class SampleController { @Autowired // service にインスタンスが割り当てられる(フィールドインジェンクション) private SampleService _service; private final SampleComponent _component; private SampleComponent _component2; @Autowired // コンストラクタインジェンクション。 public SampleController(SampleComponent component, SampleComponent component2) { this._component = component; this._component2 = component2; } SpringBoot 起動のためのアノテーション @SpringBootApplication SpringBootのアプリケーションクラスであることを示します。 Spring Initializr あたりを使ってでSpringBoot のプロジェクトを作成すると デフォルトでSpringBoot の起動用クラスが作られますが、 @SpringBootApplication アノテーションはこの起動用クラスに付与されます。 // サンプルコード @SpringBootApplication public class SpringBootSampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSampleApplication.class, args); } } コントローラー関連のアノテーション @Controller ブラウザなどからHTTPリクエストを受け付けるクラスに付与します。これを付与したコントローラークラスにはリクエストの受け付け、その後の処理をサービスクラスから呼び出します。 そのため、コントロールクラスはサービスクラスのインスタンスをメンバに持つことが多いです。 リクエストの受け付けには後述する @GetMapping や@PostMapping をメソッドに付与して実現します。 @RequestMapping このアノテーションをクラスに付与すると、設定された値は親パスとして機能します。 @GetMapping Getリクエストを受け取るためのメソッドに付与します。 @PostMapping Postリクエストを受け取るためのメソッドに付与します。 @Autowired // サンプルコード @Controller @RequestMapping("/trial") public class SampleController { @Autowired private SampleService service; @GetMapping("/sample") public String getHello() { // sample.html を開く return "sample"; } @PostMapping("/hello") public String postRequest(@RequestParam("id") String id, Model model) { SampleData sample = service.getSample(id); // 検索結果をModelに登録し、ブラウザに反映されるようにする。 model.addAttribute("feedback", sample.getName()); return "sample/response"; } } <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"></meta> <title>ResponseSample</title> </head> <body> <!-- コントローラークラスで設定した値はここに反映される --> <p th:text="${feedback}"></p> </body> </html>``` サービス関連のアノテーション @Service コントローラークラスでリクエストを受け付けた後の処理をサービスクラスで実行します。 このサービスクラスには@Services アノテーションを付与します。 サービスクラスではデータベースへの読み書きは直接行わず、後述するリポジトリクラスを経由してデータ操作を行います。 そのため、サービスクラスはリポジトリクラスのインスタンスをメンバに持つことが多いです。 @Service public class SampleService { @Autowired private SampleRepository repository; /** 従業員を1人取得する */ public SampleData getSample(String id) { // 検索する。実際のDBアクセスはリポジトリクラスに任せる。 Map<String, Object> map = repository.findById(id); // Mapから値を取得し、返却用のSampleDataクラスのインスタンスを構築していく。 String id = (String) map.get("id"); SampleData data = new SampleData(); data.setName(id); return data; } } データ操作関連のアノテーション @Repository DB操作などデータの読み書きをするためのリポジトリクラスに@Repository アノテーションを付与します。 そのため、リポジトリクラスはJdbcTemplate などのDBアクセス用クラスのインスタンスをメンバに持つことが多いです。 @Repository public class SampleRepository { @Autowired private JdbcTemplate jdbcTemplate; public Map<String, Object> findById(String id) { // SELECT文 String query = "SELECT *" + " FROM sample_table" + " WHERE id=?"; // 検索実行 Map<String, Object> result = jdbcTemplate.queryForMap(query, id); return result; } } @Data public class SampleData { private String name; } Rest実行向けアノテーション @RestController @Controller と同じくコントローラー系のクラスに付与するアノテーションですが、付与されたクラス内のメソッドの戻り値をRESTで受け取ることができるようになります(メソッドの戻り値がHTTPのレスポンスボディとして返される)。 その他色々参考 SpringBootとは? 〜DIについて〜[WIP] Spring FrameworkとDIについて Spring Bootアプリケーションのコードレビューポイント DockerでSpring Boot+CentOS+Apache+MySQLな環境を作る Spring Boot解説第18回(基本編:Controllerとは) この方の記事が一番勉強になったと思います
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む