@@ -8,6 +8,8 @@ import com.mapk.core.getAliasOrName
88import com.mapk.core.isUseDefaultArgument
99import com.mapk.core.toKConstructor
1010import java.lang.reflect.Method
11+ import java.util.concurrent.ConcurrentHashMap
12+ import java.util.concurrent.ConcurrentMap
1113import kotlin.reflect.KClass
1214import kotlin.reflect.KFunction
1315import kotlin.reflect.KParameter
@@ -31,7 +33,20 @@ class KMapper<T : Any> private constructor(
3133 .filter { it.kind != KParameter .Kind .INSTANCE && ! it.isUseDefaultArgument() }
3234 .associate { (parameterNameConverter(it.getAliasOrName()!! )) to ParameterForMap .newInstance(it) }
3335
36+ private val getCache: ConcurrentMap <KClass <* >, List < (Any , ArgumentBucket ) -> Unit >> = ConcurrentHashMap ()
37+
3438 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+
3550 src::class .memberProperties.forEach outer@{ property ->
3651 // propertyが公開されていない場合は処理を行わない
3752 if (property.visibility != KVisibility .PUBLIC ) return @outer
@@ -46,14 +61,22 @@ class KMapper<T : Any> private constructor(
4661 if (it is KGetterAlias ) alias = it.value
4762 }
4863
49- parameterMap[alias ? : property.name]?.let {
50- // javaGetterを呼び出す方が高速
64+ parameterMap[alias ? : property.name]?.let { param ->
5165 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+ // キャッシュの整合性を保つため、ここでは終了判定を行わない
5577 }
5678 }
79+ getCache.putIfAbsent(clazz, tempCacheArrayList)
5780 }
5881
5982 private fun bindArguments (argumentBucket : ArgumentBucket , src : Map <* , * >) {
0 commit comments