mirror of
https://github.com/tursom/TursomServer.git
synced 2024-12-26 21:00:41 +08:00
make Proxy run faster
This commit is contained in:
parent
68648b1f77
commit
56375ce172
@ -0,0 +1,40 @@
|
|||||||
|
package cn.tursom.proxy
|
||||||
|
|
||||||
|
import cn.tursom.reflect.asm.ReflectAsmUtils
|
||||||
|
import net.sf.cglib.core.Signature
|
||||||
|
import net.sf.cglib.proxy.Callback
|
||||||
|
import net.sf.cglib.proxy.MethodProxy
|
||||||
|
|
||||||
|
object CglibUtil {
|
||||||
|
fun getFactoryData(clazz: Class<*>): Any? {
|
||||||
|
val (fieldAccess, i) = ReflectAsmUtils.getField(clazz, "CGLIB\$FACTORY_DATA")!!
|
||||||
|
return fieldAccess.get(null, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCallbackFilter(clazz: Class<*>): Any? {
|
||||||
|
val field = clazz.getDeclaredField("CGLIB\$CALLBACK_FILTER")
|
||||||
|
field.isAccessible = true
|
||||||
|
return field.get(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findMethodProxy(clazz: Class<*>, signature: Signature): MethodProxy? {
|
||||||
|
return ReflectAsmUtils.getStaticMethod1<Signature, MethodProxy?>(
|
||||||
|
clazz,
|
||||||
|
"CGLIB\$findMethodProxy"
|
||||||
|
)!!(signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setThreadCallbacks(clazz: Class<*>, callbacks: Array<out Callback>) {
|
||||||
|
ReflectAsmUtils.getStaticMethod1<Array<out Callback>, Unit?>(
|
||||||
|
clazz,
|
||||||
|
"CGLIB\$SET_THREAD_CALLBACKS"
|
||||||
|
)!!(callbacks)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setStaticCallbacks(clazz: Class<*>, callbacks: Array<out Callback>) {
|
||||||
|
ReflectAsmUtils.getStaticMethod1<Array<out Callback>, Unit?>(
|
||||||
|
clazz,
|
||||||
|
"CGLIB\$SET_STATIC_CALLBACKS"
|
||||||
|
)!!(callbacks)
|
||||||
|
}
|
||||||
|
}
|
@ -6,27 +6,40 @@ import net.sf.cglib.proxy.Factory
|
|||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
object Proxy {
|
object Proxy {
|
||||||
val enhancerMap = ConcurrentHashMap<Class<*>, Enhancer>()
|
object CallSuperException : Exception()
|
||||||
|
|
||||||
|
val callSuper = object : ThreadLocal<Boolean>() {
|
||||||
|
override fun initialValue(): Boolean = throw CallSuperException
|
||||||
|
override fun get(): Boolean = try {
|
||||||
|
super.get()
|
||||||
|
} catch (_: CallSuperException) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultContainer: () -> MutableProxyContainer = { ListProxyContainer() }
|
||||||
private val cache = ConcurrentHashMap<Class<*>, Class<*>>()
|
private val cache = ConcurrentHashMap<Class<*>, Class<*>>()
|
||||||
|
|
||||||
private fun <T> getTarget(clazz: Class<T>): Class<T> = cache.computeIfAbsent(clazz) {
|
fun getContainer(obj: Any): ProxyContainer? {
|
||||||
val enhancer = Enhancer()
|
if (obj !is Factory) return null
|
||||||
enhancerMap[clazz] = enhancer
|
val interceptor = obj.getCallback(0) as? ProxyInterceptor ?: return null
|
||||||
enhancer.setSuperclass(clazz)
|
return interceptor.container
|
||||||
enhancer.setCallbackType(ProxyInterceptor::class.java)
|
}
|
||||||
enhancer.setCallbackFilter { 0 }
|
|
||||||
enhancer.createClass()
|
|
||||||
}.uncheckedCast()
|
|
||||||
|
|
||||||
operator fun <T> get(
|
fun addProxy(obj: Any, proxy: ProxyMethod): Boolean {
|
||||||
|
val container = getContainer(obj) ?: return false
|
||||||
|
(container as? MutableProxyContainer)?.addProxy(proxy) ?: return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator fun <T> get(
|
||||||
clazz: Class<T>,
|
clazz: Class<T>,
|
||||||
|
container: MutableProxyContainer = defaultContainer(),
|
||||||
builder: (Class<T>) -> T,
|
builder: (Class<T>) -> T,
|
||||||
): Pair<T, MutableProxyContainer> {
|
): Pair<T, MutableProxyContainer> {
|
||||||
val target = getTarget(clazz)
|
val target = getCachedTarget(clazz)
|
||||||
val container = ListProxyContainer()
|
|
||||||
val obj = builder(target)
|
val obj = builder(target)
|
||||||
obj as Factory
|
injectCallback(obj as Factory) { container }
|
||||||
obj.setCallback(0, ProxyInterceptor(container))
|
|
||||||
return obj to container
|
return obj to container
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,15 +47,42 @@ object Proxy {
|
|||||||
inline fun <reified T> get(
|
inline fun <reified T> get(
|
||||||
argumentTypes: Array<out Class<*>>,
|
argumentTypes: Array<out Class<*>>,
|
||||||
arguments: Array<out Any?>,
|
arguments: Array<out Any?>,
|
||||||
) = get(T::class.java, argumentTypes, arguments)
|
container: MutableProxyContainer = defaultContainer(),
|
||||||
|
) = get(T::class.java, argumentTypes, arguments, container)
|
||||||
|
|
||||||
operator fun <T> get(clazz: Class<T>) = get(clazz, Class<T>::newInstance)
|
operator fun <T> get(clazz: Class<T>, container: MutableProxyContainer = defaultContainer()) =
|
||||||
|
get(clazz, container, Class<T>::newInstance)
|
||||||
|
|
||||||
operator fun <T> get(
|
operator fun <T> get(
|
||||||
clazz: Class<T>,
|
clazz: Class<T>,
|
||||||
argumentTypes: Array<out Class<*>>,
|
argumentTypes: Array<out Class<*>>,
|
||||||
arguments: Array<out Any?>,
|
arguments: Array<out Any?>,
|
||||||
) = get(clazz) {
|
container: MutableProxyContainer = defaultContainer(),
|
||||||
|
) = get(clazz, container) {
|
||||||
it.getConstructor(*argumentTypes).newInstance(*arguments)
|
it.getConstructor(*argumentTypes).newInstance(*arguments)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
fun <T> newEnhancer(clazz: Class<T>, vararg interfaces: Class<*>): Enhancer {
|
||||||
|
val enhancer = Enhancer()
|
||||||
|
enhancer.setSuperclass(clazz)
|
||||||
|
if (interfaces.isNotEmpty()) {
|
||||||
|
enhancer.setInterfaces(interfaces)
|
||||||
|
}
|
||||||
|
enhancer.setCallbackType(ProxyInterceptor::class.java)
|
||||||
|
enhancer.setCallbackFilter { 0 }
|
||||||
|
return enhancer
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
inline fun injectCallback(obj: Any, container: () -> ProxyContainer = { defaultContainer() }): ProxyContainer {
|
||||||
|
obj as Factory
|
||||||
|
if (obj.getCallback(0) == null || obj.getCallback(0) == ProxyDispatcher) {
|
||||||
|
obj.setCallback(0, ProxyInterceptor(container()))
|
||||||
|
}
|
||||||
|
return (obj.getCallback(0) as ProxyInterceptor).container
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> getCachedTarget(clazz: Class<T>): Class<T> = cache.computeIfAbsent(clazz) {
|
||||||
|
newEnhancer(clazz).createClass()
|
||||||
|
}.uncheckedCast()
|
||||||
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package cn.tursom.proxy
|
|
||||||
|
|
||||||
import net.sf.cglib.proxy.MethodProxy
|
|
||||||
import java.lang.reflect.Method
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
object ProxyContainerHandlerCache {
|
|
||||||
private val handlerMap: MutableMap<MethodProxy, (Any, ProxyContainer, Method, Array<out Any?>, MethodProxy) -> ProxyResult<Any?>> =
|
|
||||||
ConcurrentHashMap()
|
|
||||||
val callSuper = { obj: Any, _: ProxyContainer, _: Method, args: Array<out Any?>, proxy: MethodProxy ->
|
|
||||||
ProxyResult.of<Any?>(proxy.invokeSuper(obj, args))
|
|
||||||
}
|
|
||||||
val empty = { _: Any, _: ProxyContainer, _: Method, _: Array<out Any?>, _: MethodProxy -> ProxyResult.failed<Any?>() }
|
|
||||||
|
|
||||||
fun getHandler(method: MethodProxy): ((Any, ProxyContainer, Method, Array<out Any?>, MethodProxy) -> ProxyResult<Any?>)? {
|
|
||||||
return handlerMap[method]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setHandler(
|
|
||||||
method: MethodProxy,
|
|
||||||
onProxy: ((Any, ProxyContainer, Method, Array<out Any?>, MethodProxy) -> ProxyResult<Any?>)?,
|
|
||||||
) {
|
|
||||||
handlerMap[method] = onProxy ?: callSuper
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,12 @@
|
|||||||
|
package cn.tursom.proxy
|
||||||
|
|
||||||
|
import net.sf.cglib.proxy.MethodInterceptor
|
||||||
|
import net.sf.cglib.proxy.MethodProxy
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
object ProxyDispatcher : MethodInterceptor {
|
||||||
|
override fun intercept(obj: Any, method: Method, args: Array<out Any>, proxy: MethodProxy): Any {
|
||||||
|
Proxy.injectCallback(obj)
|
||||||
|
return proxy(obj, args)
|
||||||
|
}
|
||||||
|
}
|
@ -2,39 +2,16 @@ package cn.tursom.proxy
|
|||||||
|
|
||||||
import net.sf.cglib.proxy.MethodInterceptor
|
import net.sf.cglib.proxy.MethodInterceptor
|
||||||
import net.sf.cglib.proxy.MethodProxy
|
import net.sf.cglib.proxy.MethodProxy
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ProxyInterceptor(
|
class ProxyInterceptor(
|
||||||
private val container: ProxyContainer = ListProxyContainer(),
|
val container: ProxyContainer = ListProxyContainer(),
|
||||||
|
// disable call super can save 20% time
|
||||||
private val supportCallSuper: Boolean = true,
|
private val supportCallSuper: Boolean = true,
|
||||||
) : MethodInterceptor {
|
) : MethodInterceptor {
|
||||||
companion object {
|
|
||||||
val callSuper = ThreadLocal<Boolean?>()
|
|
||||||
private val parameterTypes = arrayOf(Method::class.java, Array<Any>::class.java, MethodProxy::class.java)
|
|
||||||
private val parameterTypesField: Field = Method::class.java.getDeclaredField("parameterTypes").apply {
|
|
||||||
isAccessible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private fun getParameterTypes(method: Method): Array<Class<*>> {
|
|
||||||
return parameterTypesField[method] as Array<Class<*>>
|
|
||||||
}
|
|
||||||
|
|
||||||
fun equalsMethod(method: Method, name: String?, parameterTypes: Array<Class<*>>?): Boolean {
|
|
||||||
return method.name == name && parameterTypes.contentEquals(getParameterTypes(method))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isOnProxyMethod(method: Method): Boolean {
|
|
||||||
//return callSuper.get() == true || equalsMethod(method, "onProxy", parameterTypes)
|
|
||||||
return callSuper.get() == true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun intercept(obj: Any, method: Method, args: Array<out Any?>, proxy: MethodProxy): Any? {
|
override fun intercept(obj: Any, method: Method, args: Array<out Any?>, proxy: MethodProxy): Any? {
|
||||||
if (supportCallSuper && callSuper.get() == true) {
|
if (supportCallSuper && Proxy.callSuper.get()) {
|
||||||
callSuper.remove()
|
Proxy.callSuper.remove()
|
||||||
return proxy.invokeSuper(obj, args)
|
return proxy.invokeSuper(obj, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,4 +22,4 @@ class ProxyInterceptor(
|
|||||||
proxy.invokeSuper(obj, args)
|
proxy.invokeSuper(obj, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
|
|
||||||
interface ProxyMethod {
|
interface ProxyMethod {
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun onProxy(obj: Any?, method: Method, args: Array<out Any?>, proxy: MethodProxy): ProxyResult<*> {
|
fun onProxy(obj: Any, c: ProxyContainer, method: Method, args: Array<out Any?>, proxy: MethodProxy): ProxyResult<*> {
|
||||||
val handlerCacheMap = getHandlerCacheMap(javaClass)
|
val handlerCacheMap = getHandlerCacheMap(javaClass)
|
||||||
val methodResult = handlerCacheMap[method]
|
val methodResult = handlerCacheMap[method]
|
||||||
if (methodResult != null) {
|
if (methodResult != null) {
|
||||||
return if (methodResult.success) {
|
return if (methodResult.success) {
|
||||||
ProxyResult.of(methodResult.result(this, args))
|
methodResult.result(this, args)
|
||||||
} else {
|
} else {
|
||||||
ProxyResult.failed<Any>()
|
ProxyResult.failed<Any>()
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ interface ProxyMethod {
|
|||||||
if (reflectAsmMethod != null) {
|
if (reflectAsmMethod != null) {
|
||||||
val (methodAccess, index) = reflectAsmMethod
|
val (methodAccess, index) = reflectAsmMethod
|
||||||
handlerCacheMap[method] = ProxyResult({ p, a ->
|
handlerCacheMap[method] = ProxyResult({ p, a ->
|
||||||
methodAccess.invoke(p, index, *a)
|
ProxyResult.of(methodAccess.invoke(p, index, *a))
|
||||||
}, true)
|
}, true)
|
||||||
return ProxyResult.of(methodAccess.invoke(this, index, *args))
|
return ProxyResult.of(methodAccess.invoke(this, index, *args))
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ interface ProxyMethod {
|
|||||||
selfMethod = javaClass.getMethod(methodName, *method.parameterTypes)
|
selfMethod = javaClass.getMethod(methodName, *method.parameterTypes)
|
||||||
selfMethod.isAccessible = true
|
selfMethod.isAccessible = true
|
||||||
handlerCacheMap[method] = ProxyResult({ p, a ->
|
handlerCacheMap[method] = ProxyResult({ p, a ->
|
||||||
selfMethod(p, *a)
|
ProxyResult.of(selfMethod(p, *a))
|
||||||
}, true)
|
}, true)
|
||||||
return ProxyResult.of<Any>(selfMethod(this, *args))
|
return ProxyResult.of<Any>(selfMethod(this, *args))
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
@ -70,11 +70,11 @@ interface ProxyMethod {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val handlerCacheMapMap: MutableMap<
|
private val handlerCacheMapMap: MutableMap<
|
||||||
Class<out ProxyMethod>,
|
Class<out ProxyMethod>,
|
||||||
MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> Any?>>> =
|
MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> ProxyResult<*>>>> =
|
||||||
HashMap()
|
HashMap()
|
||||||
|
|
||||||
fun getHandlerCacheMap(type: Class<out ProxyMethod>): MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> Any?>> {
|
fun getHandlerCacheMap(type: Class<out ProxyMethod>): MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> ProxyResult<*>>> {
|
||||||
var handlerCacheMap = handlerCacheMapMap[type]
|
var handlerCacheMap = handlerCacheMapMap[type]
|
||||||
if (handlerCacheMap == null) synchronized(handlerCacheMapMap) {
|
if (handlerCacheMap == null) synchronized(handlerCacheMapMap) {
|
||||||
handlerCacheMap = handlerCacheMapMap[type]
|
handlerCacheMap = handlerCacheMapMap[type]
|
||||||
|
@ -2,31 +2,34 @@ package cn.tursom.proxy
|
|||||||
|
|
||||||
import net.sf.cglib.proxy.MethodProxy
|
import net.sf.cglib.proxy.MethodProxy
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
typealias ProxyMethodCacheFunction = (obj: Any?, method: Method, args: Array<out Any?>, proxy: MethodProxy) -> ProxyResult<*>
|
typealias ProxyMethodCacheFunction = (obj: Any, c: ProxyContainer, method: Method, args: Array<out Any?>, proxy: MethodProxy) -> ProxyResult<*>
|
||||||
|
|
||||||
class ProxyMethodCache(
|
class ProxyMethodCache(
|
||||||
private var lastModify: Long = 0,
|
private var lastModify: Long = 0,
|
||||||
private var function: ProxyMethodCacheFunction = failed,
|
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val failed: ProxyMethodCacheFunction = { _, _, _, _ -> ProxyResult.failed }
|
val failed: ProxyMethodCacheFunction = { _, _, _, _, _ -> ProxyResult.failed }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(lastModify: Long, function: ProxyMethodCacheFunction = this.function) {
|
private val functionMap = ConcurrentHashMap<MethodProxy, ProxyMethodCacheFunction>()
|
||||||
|
|
||||||
|
fun update(lastModify: Long, proxy: MethodProxy, function: ProxyMethodCacheFunction = functionMap[proxy] ?: failed) {
|
||||||
this.lastModify = lastModify
|
this.lastModify = lastModify
|
||||||
this.function = function
|
functionMap[proxy] = function
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
lastModify: Long,
|
lastModify: Long,
|
||||||
obj: Any?,
|
obj: Any,
|
||||||
|
c: ProxyContainer,
|
||||||
method: Method,
|
method: Method,
|
||||||
args: Array<out Any?>,
|
args: Array<out Any?>,
|
||||||
proxy: MethodProxy,
|
proxy: MethodProxy,
|
||||||
): ProxyResult<*>? = if (lastModify != this.lastModify) {
|
): ProxyResult<*>? = if (lastModify != this.lastModify) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
function(obj, method, args, proxy)
|
(functionMap[proxy] ?: failed)(obj, c, method, args, proxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ import cn.tursom.core.uncheckedCast
|
|||||||
data class ProxyResult<out R>(
|
data class ProxyResult<out R>(
|
||||||
val result: R,
|
val result: R,
|
||||||
val success: Boolean = false,
|
val success: Boolean = false,
|
||||||
val cache: Boolean = false,
|
val cache: Boolean = true,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
val success: ProxyResult<*> = ProxyResult<Any?>(null, true)
|
val success: ProxyResult<*> = ProxyResult<Any?>(null, true)
|
||||||
|
@ -12,10 +12,8 @@ import java.util.*
|
|||||||
|
|
||||||
object ProxyRunner {
|
object ProxyRunner {
|
||||||
private val errMsgSearchList = arrayOf("%M", "%B", "%A")
|
private val errMsgSearchList = arrayOf("%M", "%B", "%A")
|
||||||
private val forFirstProxyCacheKey =
|
private val proxyMethodCacheKey = ProxyContainer.contextEnv.newKey<ProxyMethodCache>()
|
||||||
ProxyContainer.contextEnv.newKey<ProxyMethodCache>().withDefault { ProxyMethodCache() }
|
.withDefault { ProxyMethodCache() }
|
||||||
private val forEachProxyCacheKey =
|
|
||||||
ProxyContainer.contextEnv.newKey<ProxyMethodCache>().withDefault { ProxyMethodCache() }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* will be call when proxy method invoke.
|
* will be call when proxy method invoke.
|
||||||
@ -23,10 +21,12 @@ object ProxyRunner {
|
|||||||
*/
|
*/
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun onProxy(obj: Any, c: ProxyContainer, method: Method, args: Array<out Any?>, proxy: MethodProxy): ProxyResult<*> {
|
fun onProxy(obj: Any, c: ProxyContainer, method: Method, args: Array<out Any?>, proxy: MethodProxy): ProxyResult<*> {
|
||||||
var handler = ProxyContainerHandlerCache.getHandler(proxy)
|
val cache = c.context[proxyMethodCacheKey]
|
||||||
if (handler != null) {
|
cache(c.lastModify, obj, c, method, args, proxy)?.let {
|
||||||
return handler(obj, c, method, args, proxy)
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var handler: ProxyMethodCacheFunction? = null
|
||||||
for (annotation in method.annotations) when (annotation) {
|
for (annotation in method.annotations) when (annotation) {
|
||||||
is ForEachProxy -> {
|
is ForEachProxy -> {
|
||||||
handler = onForeachProxy(annotation)
|
handler = onForeachProxy(annotation)
|
||||||
@ -41,18 +41,17 @@ object ProxyRunner {
|
|||||||
//handler = ProxyContainerHandlerCache.callSuper
|
//handler = ProxyContainerHandlerCache.callSuper
|
||||||
handler = onForFirstProxy(ForFirstProxy.EMPTY)
|
handler = onForFirstProxy(ForFirstProxy.EMPTY)
|
||||||
}
|
}
|
||||||
ProxyContainerHandlerCache.setHandler(proxy, handler)
|
|
||||||
return handler(obj, c, method, args, proxy)
|
return handler(obj, c, method, args, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onForFirstProxy(forFirstProxy: ForFirstProxy): (Any, ProxyContainer, Method, Array<out Any?>, MethodProxy) -> ProxyResult<*> {
|
fun onForFirstProxy(forFirstProxy: ForFirstProxy): ProxyMethodCacheFunction {
|
||||||
return { o: Any, c: ProxyContainer, m: Method, a: Array<out Any?>, p: MethodProxy ->
|
val classes = when (forFirstProxy.value.size) {
|
||||||
c.context[forFirstProxyCacheKey](c.lastModify, o, m, a, p) ?: onForFirstProxy(o, c, m, a, p, forFirstProxy,
|
0 -> emptyList()
|
||||||
when (forFirstProxy.value.size) {
|
1 -> listOf(forFirstProxy.value[0].java)
|
||||||
0 -> emptyList()
|
else -> forFirstProxy.value.asSequence().map { it.java }.toSet()
|
||||||
1 -> listOf(forFirstProxy.value[0].java)
|
}
|
||||||
else -> forFirstProxy.value.asSequence().map { it.java }.toSet()
|
return { o, c, m: Method, a, p ->
|
||||||
})
|
onForFirstProxy(o, c, m, a, p, forFirstProxy, classes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,12 +64,11 @@ object ProxyRunner {
|
|||||||
forFirstProxy: ForFirstProxy,
|
forFirstProxy: ForFirstProxy,
|
||||||
classes: Collection<Class<*>>,
|
classes: Collection<Class<*>>,
|
||||||
): ProxyResult<*> {
|
): ProxyResult<*> {
|
||||||
val cache = container.context[forFirstProxyCacheKey]
|
|
||||||
val result = container.forFirstProxy { p ->
|
val result = container.forFirstProxy { p ->
|
||||||
if (classes.isEmpty() || classes.stream().anyMatch { c: Class<*> -> c.isInstance(p) }) {
|
if (classes.isEmpty() || classes.stream().anyMatch { c: Class<*> -> c.isInstance(p) }) {
|
||||||
val result = p.onProxy(obj, method, args, proxy)
|
val result = p.onProxy(obj, container, method, args, proxy)
|
||||||
if (forFirstProxy.cache && result.success && result.cache) {
|
if (forFirstProxy.cache && result.success && result.cache) {
|
||||||
cache.update(container.lastModify, p::onProxy)
|
container.context[proxyMethodCacheKey].update(container.lastModify, proxy, p::onProxy)
|
||||||
}
|
}
|
||||||
return@forFirstProxy result
|
return@forFirstProxy result
|
||||||
} else {
|
} else {
|
||||||
@ -103,34 +101,48 @@ object ProxyRunner {
|
|||||||
errMsg = StringUtils.replaceEach(errMsg, errMsgSearchList, replacementList)
|
errMsg = StringUtils.replaceEach(errMsg, errMsgSearchList, replacementList)
|
||||||
val exceptionConstructor = forFirstProxy.errClass.java.getConstructor(String::class.java)
|
val exceptionConstructor = forFirstProxy.errClass.java.getConstructor(String::class.java)
|
||||||
if (forFirstProxy.cache) {
|
if (forFirstProxy.cache) {
|
||||||
cache.update(container.lastModify) { _, _, _, _ ->
|
container.context[proxyMethodCacheKey].update(container.lastModify, proxy) { _, _, _, _, _ ->
|
||||||
throw exceptionConstructor.newInstance(errMsg)
|
throw exceptionConstructor.newInstance(errMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw exceptionConstructor.newInstance(errMsg)
|
throw exceptionConstructor.newInstance(errMsg)
|
||||||
}
|
}
|
||||||
if (forFirstProxy.cache) {
|
if (forFirstProxy.cache) {
|
||||||
cache.update(container.lastModify)
|
container.context[proxyMethodCacheKey].update(container.lastModify, proxy)
|
||||||
}
|
}
|
||||||
return ProxyResult.failed
|
return ProxyResult.failed
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onForeachProxy(forEachProxy: ForEachProxy) = onForeachProxy(when (forEachProxy.value.size) {
|
fun onForeachProxy(forEachProxy: ForEachProxy) = onForeachProxy(when (forEachProxy.value.size) {
|
||||||
0 -> emptyList()
|
0 -> emptyList()
|
||||||
1 -> listOf(forEachProxy.value[0].java)
|
1 -> listOf(forEachProxy.value[0].java)
|
||||||
else -> forEachProxy.value.asSequence().map { it.java }.toSet()
|
else -> forEachProxy.value.asSequence().map { it.java }.toSet()
|
||||||
})
|
}, forEachProxy.cache)
|
||||||
|
|
||||||
|
private val emptyProxyList = ArrayList<ProxyMethod>()
|
||||||
private fun onForeachProxy(
|
private fun onForeachProxy(
|
||||||
classes: Collection<Class<*>>,
|
classes: Collection<Class<*>>,
|
||||||
): (Any, ProxyContainer, Method, Array<out Any?>, MethodProxy) -> ProxyResult<Any?> {
|
cache: Boolean,
|
||||||
return (label@{ o: Any, c: ProxyContainer, m: Method, a: Array<out Any?>, proxy1: MethodProxy ->
|
): ProxyMethodCacheFunction = { o, c, m, a, proxy ->
|
||||||
c.forEachProxy { p ->
|
val proxyList = if (cache) ArrayList<ProxyMethod>() else emptyProxyList
|
||||||
if (classes.isEmpty() || classes.any { c: Class<*> -> c.isInstance(p) }) {
|
c.forEachProxy { p ->
|
||||||
p.onProxy(o, m, a, proxy1)
|
if (classes.isEmpty() || classes.any { c: Class<*> -> c.isInstance(p) }) {
|
||||||
|
val result = p.onProxy(o, c, m, a, proxy)
|
||||||
|
if (cache && result.success) {
|
||||||
|
proxyList.add(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProxyResult.failed<Any?>()
|
}
|
||||||
})
|
if (cache) {
|
||||||
|
c.context[proxyMethodCacheKey].update(c.lastModify, proxy, onCachedForeachProxy((proxyList)))
|
||||||
|
}
|
||||||
|
ProxyResult.failed<Any?>()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCachedForeachProxy(proxyList: List<ProxyMethod>): ProxyMethodCacheFunction = { o, c, m, a, proxy ->
|
||||||
|
proxyList.forEach { p ->
|
||||||
|
p.onProxy(o, c, m, a, proxy)
|
||||||
|
}
|
||||||
|
ProxyResult.failed<Any?>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,8 @@ import kotlin.reflect.KClass
|
|||||||
|
|
||||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
annotation class ForEachProxy(vararg val value: KClass<*> = [], val name: String = "")
|
annotation class ForEachProxy(
|
||||||
|
vararg val value: KClass<*> = [],
|
||||||
|
val name: String = "",
|
||||||
|
val cache: Boolean = true,
|
||||||
|
)
|
@ -1,6 +1,8 @@
|
|||||||
package cn.tursom.proxy
|
package cn.tursom.proxy
|
||||||
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.objectweb.asm.ClassWriter
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class Example {
|
class Example {
|
||||||
open class TestClass protected constructor() {
|
open class TestClass protected constructor() {
|
||||||
@ -12,14 +14,54 @@ class Example {
|
|||||||
private val t: TestClass,
|
private val t: TestClass,
|
||||||
) : ProxyMethod {
|
) : ProxyMethod {
|
||||||
fun getA(): Int {
|
fun getA(): Int {
|
||||||
ProxyInterceptor.callSuper.set(true)
|
Proxy.callSuper.set(true)
|
||||||
return t.a + 1
|
return t.a + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getClass() {
|
||||||
|
val writer = ClassWriter(0)
|
||||||
|
val enhancer = Proxy.newEnhancer(TestClass::class.java)
|
||||||
|
val clazz = enhancer.createClass()
|
||||||
|
CglibUtil.setStaticCallbacks(clazz, arrayOf(ProxyInterceptor()))
|
||||||
|
val instance = clazz.newInstance()
|
||||||
|
enhancer.generateClass(writer)
|
||||||
|
File("TestClass.class").writeBytes(writer.toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test() {
|
fun test() {
|
||||||
|
//val enhancer = Enhancer()
|
||||||
|
//enhancer.setSuperclass(TestClass::class.java)
|
||||||
|
//enhancer.setCallback(ProxyDispatcher)
|
||||||
|
//val t = enhancer.create() as TestClass
|
||||||
|
//val enhancer = Enhancer()
|
||||||
|
//enhancer.setSuperclass(TestClass::class.java)
|
||||||
|
//enhancer.setCallback(ProxyRefDispatcher {
|
||||||
|
// println("on Dispatcher")
|
||||||
|
// ProxyInterceptor()
|
||||||
|
//})
|
||||||
|
//
|
||||||
|
//val t = enhancer.create() as TestClass
|
||||||
|
//val writer = ClassWriter(0)
|
||||||
|
//enhancer.generateClass(writer)
|
||||||
|
//File("TestClass_ProxyRefDispatcher.class").writeBytes(writer.toByteArray())
|
||||||
|
val (t, container) = Proxy.get<TestClass>()
|
||||||
|
//val t = Proxy.getCachedTarget(TestClass::class.java).newInstance()
|
||||||
|
//val container = Proxy.injectCallback(t)
|
||||||
|
//container as MutableProxyContainer
|
||||||
|
container.addProxy(GetA(t))
|
||||||
|
|
||||||
|
println(t.javaClass)
|
||||||
|
repeat(10) {
|
||||||
|
t.a = t.a
|
||||||
|
println(t.a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun benchmark() {
|
||||||
val (t, container) = Proxy.get<TestClass>()
|
val (t, container) = Proxy.get<TestClass>()
|
||||||
container.addProxy(GetA(t))
|
container.addProxy(GetA(t))
|
||||||
|
|
||||||
|
@ -91,41 +91,54 @@ object ReflectAsmUtils {
|
|||||||
returnType = method.returnType,
|
returnType = method.returnType,
|
||||||
)
|
)
|
||||||
|
|
||||||
inline fun <reified T, reified R> getMethod0(methodName: String): (T.() -> R)? {
|
inline fun <reified T, reified R> getMethod0(
|
||||||
val (methodAccess, index) = getMethod(T::class.java, methodName, returnType = R::class.java)
|
methodName: String,
|
||||||
|
type: Class<T> = T::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.() -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return {
|
return {
|
||||||
methodAccess.invoke(this, index) as R
|
methodAccess.invoke(this, index) as R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified R> getMethod1(methodName: String): (T.(A1) -> R)? {
|
inline fun <reified T, reified A1, reified R> getMethod1(
|
||||||
val (methodAccess, index) = getMethod(T::class.java, methodName, A1::class.java, returnType = R::class.java)
|
methodName: String,
|
||||||
|
type: Class<T> = T::class.java,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1 ->
|
return { a1 ->
|
||||||
methodAccess.invoke(this, index, a1) as R
|
methodAccess.invoke(this, index, a1) as R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified A2, reified R> getMethod2(methodName: String): (T.(A1, A2) -> R)? {
|
inline fun <reified T, reified A1, reified A2, reified R> getMethod2(
|
||||||
val (methodAccess, index) = getMethod(T::class.java,
|
methodName: String,
|
||||||
methodName,
|
type: Class<T> = T::class.java,
|
||||||
A1::class.java,
|
ta1: Class<A1> = A1::class.java,
|
||||||
A2::class.java,
|
ta2: Class<A2> = A2::class.java,
|
||||||
returnType = R::class.java)
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1, A2) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1, a2 ->
|
return { a1, a2 ->
|
||||||
methodAccess.invoke(this, index, a1, a2) as R
|
methodAccess.invoke(this, index, a1, a2) as R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified A2, reified A3, reified R> getMethod3(methodName: String): (T.(A1, A2, A3) -> R)? {
|
inline fun <reified T, reified A1, reified A2, reified A3, reified R> getMethod3(
|
||||||
val (methodAccess, index) = getMethod(T::class.java,
|
methodName: String,
|
||||||
methodName,
|
type: Class<T> = T::class.java,
|
||||||
A1::class.java,
|
ta1: Class<A1> = A1::class.java,
|
||||||
A2::class.java,
|
ta2: Class<A2> = A2::class.java,
|
||||||
A3::class.java,
|
ta3: Class<A3> = A3::class.java,
|
||||||
returnType = R::class.java)
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1, A2, A3) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1, a2, a3 ->
|
return { a1, a2, a3 ->
|
||||||
methodAccess.invoke(this, index, a1, a2, a3) as R
|
methodAccess.invoke(this, index, a1, a2, a3) as R
|
||||||
@ -133,14 +146,16 @@ object ReflectAsmUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified R>
|
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified R>
|
||||||
getMethod4(methodName: String): (T.(A1, A2, A3, A4) -> R)? {
|
getMethod4(
|
||||||
val (methodAccess, index) = getMethod(T::class.java,
|
methodName: String,
|
||||||
methodName,
|
type: Class<T> = T::class.java,
|
||||||
A1::class.java,
|
ta1: Class<A1> = A1::class.java,
|
||||||
A2::class.java,
|
ta2: Class<A2> = A2::class.java,
|
||||||
A3::class.java,
|
ta3: Class<A3> = A3::class.java,
|
||||||
A4::class.java,
|
ta4: Class<A4> = A4::class.java,
|
||||||
returnType = R::class.java)
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1, A2, A3, A4) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1, a2, a3, a4 ->
|
return { a1, a2, a3, a4 ->
|
||||||
methodAccess.invoke(this, index, a1, a2, a3, a4) as R
|
methodAccess.invoke(this, index, a1, a2, a3, a4) as R
|
||||||
@ -148,15 +163,17 @@ object ReflectAsmUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified A5, reified R>
|
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified A5, reified R>
|
||||||
getMethod5(methodName: String): (T.(A1, A2, A3, A4, A5) -> R)? {
|
getMethod5(
|
||||||
val (methodAccess, index) = getMethod(T::class.java,
|
methodName: String,
|
||||||
methodName,
|
type: Class<T> = T::class.java,
|
||||||
A1::class.java,
|
ta1: Class<A1> = A1::class.java,
|
||||||
A2::class.java,
|
ta2: Class<A2> = A2::class.java,
|
||||||
A3::class.java,
|
ta3: Class<A3> = A3::class.java,
|
||||||
A4::class.java,
|
ta4: Class<A4> = A4::class.java,
|
||||||
A5::class.java,
|
ta5: Class<A5> = A5::class.java,
|
||||||
returnType = R::class.java)
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1, A2, A3, A4, A5) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, ta5, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1, a2, a3, a4, a5 ->
|
return { a1, a2, a3, a4, a5 ->
|
||||||
methodAccess.invoke(this, index, a1, a2, a3, a4, a5) as R
|
methodAccess.invoke(this, index, a1, a2, a3, a4, a5) as R
|
||||||
@ -164,19 +181,126 @@ object ReflectAsmUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified R>
|
inline fun <reified T, reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified R>
|
||||||
getMethod6(methodName: String): (T.(A1, A2, A3, A4, A5, A6) -> R)? {
|
getMethod6(
|
||||||
val (methodAccess, index) = getMethod(T::class.java,
|
methodName: String,
|
||||||
methodName,
|
type: Class<T> = T::class.java,
|
||||||
A1::class.java,
|
ta1: Class<A1> = A1::class.java,
|
||||||
A2::class.java,
|
ta2: Class<A2> = A2::class.java,
|
||||||
A3::class.java,
|
ta3: Class<A3> = A3::class.java,
|
||||||
A4::class.java,
|
ta4: Class<A4> = A4::class.java,
|
||||||
A5::class.java,
|
ta5: Class<A5> = A5::class.java,
|
||||||
A6::class.java,
|
ta6: Class<A6> = A6::class.java,
|
||||||
returnType = R::class.java)
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (T.(A1, A2, A3, A4, A5, A6) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, ta5, ta6, returnType = returnType)
|
||||||
?: return null
|
?: return null
|
||||||
return { a1, a2, a3, a4, a5, a6 ->
|
return { a1, a2, a3, a4, a5, a6 ->
|
||||||
methodAccess.invoke(this, index, a1, a2, a3, a4, a5, a6) as R
|
methodAccess.invoke(this, index, a1, a2, a3, a4, a5, a6) as R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified R> getStaticMethod0(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): (() -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return {
|
||||||
|
methodAccess.invoke(null, index) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified R> getStaticMethod1(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1 ->
|
||||||
|
methodAccess.invoke(null, index, a1) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified A2, reified R> getStaticMethod2(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
ta2: Class<A2> = A2::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1, A2) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1, a2 ->
|
||||||
|
methodAccess.invoke(null, index, a1, a2) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified A2, reified A3, reified R> getStaticMethod3(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
ta2: Class<A2> = A2::class.java,
|
||||||
|
ta3: Class<A3> = A3::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1, A2, A3) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1, a2, a3 ->
|
||||||
|
methodAccess.invoke(null, index, a1, a2, a3) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified A2, reified A3, reified A4, reified R> getStaticMethod4(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
ta2: Class<A2> = A2::class.java,
|
||||||
|
ta3: Class<A3> = A3::class.java,
|
||||||
|
ta4: Class<A4> = A4::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1, A2, A3, A4) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1, a2, a3, a4 ->
|
||||||
|
methodAccess.invoke(null, index, a1, a2, a3, a4) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified A2, reified A3, reified A4, reified A5, reified R> getStaticMethod5(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
ta2: Class<A2> = A2::class.java,
|
||||||
|
ta3: Class<A3> = A3::class.java,
|
||||||
|
ta4: Class<A4> = A4::class.java,
|
||||||
|
ta5: Class<A5> = A5::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1, A2, A3, A4, A5) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, ta5, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1, a2, a3, a4, a5 ->
|
||||||
|
methodAccess.invoke(null, index, a1, a2, a3, a4, a5) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified A1, reified A2, reified A3, reified A4, reified A5, reified A6, reified R> getStaticMethod6(
|
||||||
|
type: Class<*>,
|
||||||
|
methodName: String,
|
||||||
|
ta1: Class<A1> = A1::class.java,
|
||||||
|
ta2: Class<A2> = A2::class.java,
|
||||||
|
ta3: Class<A3> = A3::class.java,
|
||||||
|
ta4: Class<A4> = A4::class.java,
|
||||||
|
ta5: Class<A5> = A5::class.java,
|
||||||
|
ta6: Class<A6> = A6::class.java,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
): ((A1, A2, A3, A4, A5, A6) -> R)? {
|
||||||
|
val (methodAccess, index) = getMethod(type, methodName, ta1, ta2, ta3, ta4, ta5, ta6, returnType = returnType)
|
||||||
|
?: return null
|
||||||
|
return { a1, a2, a3, a4, a5, a6 ->
|
||||||
|
methodAccess.invoke(null, index, a1, a2, a3, a4, a5, a6) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class ExtSqlDialect(
|
|||||||
) : SqlDialect by sqlDialect {
|
) : SqlDialect by sqlDialect {
|
||||||
override fun createSqlFormatter(database: Database, beautifySql: Boolean, indentSize: Int): SqlFormatter {
|
override fun createSqlFormatter(database: Database, beautifySql: Boolean, indentSize: Int): SqlFormatter {
|
||||||
val formatter = sqlDialect.createSqlFormatter(database, beautifySql, indentSize)
|
val formatter = sqlDialect.createSqlFormatter(database, beautifySql, indentSize)
|
||||||
val (proxyFormatter, container) = Proxy[formatter.javaClass, InstantAllocator::get]
|
val (proxyFormatter, container) = Proxy.get(formatter.javaClass) { InstantAllocator(it) }
|
||||||
run {
|
run {
|
||||||
val extSqlFormatter = ExtSqlFormatter(formatter)
|
val extSqlFormatter = ExtSqlFormatter(formatter)
|
||||||
extSqlFormatter.registerVisitor(DirectSqlExpression.visitor)
|
extSqlFormatter.registerVisitor(DirectSqlExpression.visitor)
|
||||||
|
Loading…
Reference in New Issue
Block a user