@@ -8,6 +8,8 @@ import com.mapk.core.getAliasOrName
8
8
import com.mapk.core.isUseDefaultArgument
9
9
import com.mapk.core.toKConstructor
10
10
import java.lang.reflect.Method
11
+ import java.util.concurrent.ConcurrentHashMap
12
+ import java.util.concurrent.ConcurrentMap
11
13
import kotlin.reflect.KClass
12
14
import kotlin.reflect.KFunction
13
15
import kotlin.reflect.KParameter
@@ -31,7 +33,20 @@ class KMapper<T : Any> private constructor(
31
33
.filter { it.kind != KParameter .Kind .INSTANCE && ! it.isUseDefaultArgument() }
32
34
.associate { (parameterNameConverter(it.getAliasOrName()!! )) to ParameterForMap .newInstance(it) }
33
35
36
+ private val getCache: ConcurrentMap <KClass <* >, List < (Any , ArgumentBucket ) -> Unit >> = ConcurrentHashMap ()
37
+
34
38
private fun bindArguments (argumentBucket : ArgumentBucket , src : Any ) {
39
+ val clazz = src::class
40
+
41
+ // キャッシュヒットしたら登録した内容に沿って取得処理を行う
42
+ getCache[clazz]?.let { getters ->
43
+ // 取得対象フィールドは十分絞り込んでいると考えられるため、終了判定は行わない
44
+ getters.forEach { it(src, argumentBucket) }
45
+ return
46
+ }
47
+
48
+ val tempCacheArrayList = ArrayList < (Any , ArgumentBucket ) -> Unit > ()
49
+
35
50
src::class .memberProperties.forEach outer@{ property ->
36
51
// propertyが公開されていない場合は処理を行わない
37
52
if (property.visibility != KVisibility .PUBLIC ) return @outer
@@ -46,14 +61,22 @@ class KMapper<T : Any> private constructor(
46
61
if (it is KGetterAlias ) alias = it.value
47
62
}
48
63
49
- parameterMap[alias ? : property.name]?.let {
50
- // javaGetterを呼び出す方が高速
64
+ parameterMap[alias ? : property.name]?.let { param ->
51
65
javaGetter.isAccessible = true
52
- argumentBucket.putIfAbsent(it.param, javaGetter.invoke(src)?.let { value -> it.mapObject(value) })
53
- // 終了判定
54
- if (argumentBucket.isInitialized) return
66
+
67
+ val tempCache = { value: Any , bucket: ArgumentBucket ->
68
+ // 初期化済みであれば高コストな取得処理は行わない
69
+ if (! bucket.containsKey(param.param)) {
70
+ // javaGetterを呼び出す方が高速
71
+ bucket.putIfAbsent(param.param, javaGetter.invoke(value)?.let { param.mapObject(it) })
72
+ }
73
+ }
74
+ tempCache(src, argumentBucket)
75
+ tempCacheArrayList.add(tempCache)
76
+ // キャッシュの整合性を保つため、ここでは終了判定を行わない
55
77
}
56
78
}
79
+ getCache.putIfAbsent(clazz, tempCacheArrayList)
57
80
}
58
81
59
82
private fun bindArguments (argumentBucket : ArgumentBucket , src : Map <* , * >) {
0 commit comments