Help us understand the problem. What is going on with this article?

A Kotlinwork Locator: ことりん仕掛けのロケーター

ジャバの異常な愛情 またはSpringはいかにしてモダンであることを止めて時代遅れになったのか」で言及されていたServiceLocatorをKotlinで作ってみました。

https://github.com/dobashi/kasl

機能

機能 - 実装済

  • Locatorからのインスタンスの取り出し
  • Singleton/Prototypeの使い分け
  • Mockへの入れ替え

これだけやって2クラスで60行も行かないんだからもうJavaには戻れない・・

機能 - TODO

  • Enhancerによるカスタマイズを、利用側がInterceptorを書くだけで実装できるようにする
  • Locator自体のインスタンスをカスタマイズに応じて複数扱えるようにする

機能に対する要望等あれば可能な限り対応します。

解説 - TODO

テスト

サンプルテスト 実装済み

こんな感じでターゲットクラスAとモッククラスMockedAを作っておきます。

package com.lavans.kasl

open class A {
    open fun say() = "A: Hello!"
}

class MockedA : A() {
    override fun say() = "MockedA: Yo!"
}

kotlinだとoverrideするメソッドはopenにしておかなきゃいけなくて、テストのためにインターフェースを変えるのは良くなさそう。拡張メソッドでどうにかならないかな。

1) 設定一切なしでインスタンス取得

    @Test
    fun `A says Hello!`() {
        val a = Locator.get<A>(A::class)
        println(a.say())
        assertEquals("A: Hello!", a.say())
    }

ちゃんとA: Hello!が出力される。

2) AをMockedAに差し替え設定をしてから取得してみる

    @Test
    fun `MockedA says Yo!`() {
        Locator.put(A::class, MockedA::class)
        val a = Locator.get<A>(A::class)
        println(a.say())
        assertTrue(a.say().contains("Yo"))
    }

たしかに振る舞いが変わった。

3) デフォルトのsingletonでは何回getしても同じインスタンスが取れること

    @Test
    fun `Singleton returns same instance`(){
        val a = Locator.get<A>(A::class)
        val b = Locator.get<A>(A::class)
        val c = Locator.get<A>(A::class)
        val d = Locator.get<A>(A::class)
        println("$a\n$b\n$c\n$d")
        assertEquals(a, b)
        assertEquals(a, c)
        assertEquals(a, d)
    }

ちゃんと同じobject idで帰ってきますね

com.lavans.kasl.A@41675a1f
com.lavans.kasl.A@41675a1f
com.lavans.kasl.A@41675a1f
com.lavans.kasl.A@41675a1f

4) プロトタイプ指定すると別々のインスタンスになる

    @Test
    fun `Prototype returns different instance`(){
        Locator.put(A::class, type = KClassInfo.Type.Prototype)
        val a = Locator.get<A>(A::class)
        val b = Locator.get<A>(A::class)
        val c = Locator.get<A>(A::class)
        val d = Locator.get<A>(A::class)
        println("$a\n$b\n$c\n$d")
        assertNotEquals(a, b)
        assertNotEquals(a, c)
        assertNotEquals(a, d)
    }

なるほどー、全部違うIDだ。

com.lavans.kasl.A@309bde2d
com.lavans.kasl.A@42eda0a8
com.lavans.kasl.A@400f3528
com.lavans.kasl.A@522b5d4c

サンプル TODO

  • AOPでloggerを差し込んでmethodの開始と終了でlogを吐くやつやりたい。そうするとloggerとcglibへの依存が増えるな、増やしたくないな、別プロジェクトでもいいけど
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした