mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-14 03:40:06 +08:00
fix bugs and reconstruct
This commit is contained in:
parent
225adfa9fc
commit
acf16136a4
@ -29,4 +29,4 @@ class ListProxyContainer(
|
||||
lastModify = System.currentTimeMillis()
|
||||
return proxyList.iterator()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,33 +27,33 @@ object Proxy {
|
||||
}
|
||||
|
||||
fun addProxy(obj: Any, proxy: ProxyMethod): Boolean {
|
||||
val container = getContainer(obj) ?: return false
|
||||
(container as? MutableProxyContainer)?.addProxy(proxy) ?: return false
|
||||
val container = getContainer(obj) as? MutableProxyContainer ?: return false
|
||||
container.addProxy(proxy)
|
||||
return true
|
||||
}
|
||||
|
||||
inline operator fun <T> get(
|
||||
inline operator fun <T : Any> get(
|
||||
clazz: Class<T>,
|
||||
container: MutableProxyContainer = defaultContainer(),
|
||||
builder: (Class<T>) -> T,
|
||||
): Pair<T, MutableProxyContainer> {
|
||||
val target = getCachedTarget(clazz)
|
||||
val obj = builder(target)
|
||||
injectCallback(obj as Factory) { container }
|
||||
injectCallback(obj as Factory, container)
|
||||
return obj to container
|
||||
}
|
||||
|
||||
inline fun <reified T> get() = get(T::class.java)
|
||||
inline fun <reified T> get(
|
||||
inline fun <reified T : Any> get() = get(T::class.java)
|
||||
inline fun <reified T : Any> get(
|
||||
argumentTypes: Array<out Class<*>>,
|
||||
arguments: Array<out Any?>,
|
||||
container: MutableProxyContainer = defaultContainer(),
|
||||
) = get(T::class.java, argumentTypes, arguments, container)
|
||||
|
||||
operator fun <T> get(clazz: Class<T>, container: MutableProxyContainer = defaultContainer()) =
|
||||
operator fun <T : Any> get(clazz: Class<T>, container: MutableProxyContainer = defaultContainer()) =
|
||||
get(clazz, container, Class<T>::newInstance)
|
||||
|
||||
operator fun <T> get(
|
||||
operator fun <T : Any> get(
|
||||
clazz: Class<T>,
|
||||
argumentTypes: Array<out Class<*>>,
|
||||
arguments: Array<out Any?>,
|
||||
@ -62,7 +62,7 @@ object Proxy {
|
||||
it.getConstructor(*argumentTypes).newInstance(*arguments)
|
||||
}
|
||||
|
||||
fun <T> newEnhancer(clazz: Class<T>, vararg interfaces: Class<*>): Enhancer {
|
||||
fun <T : Any> newEnhancer(clazz: Class<T>, vararg interfaces: Class<*>): Enhancer {
|
||||
val enhancer = Enhancer()
|
||||
enhancer.setSuperclass(clazz)
|
||||
if (interfaces.isNotEmpty()) {
|
||||
@ -74,15 +74,17 @@ object Proxy {
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
inline fun injectCallback(obj: Any, container: () -> ProxyContainer = { defaultContainer() }): ProxyContainer {
|
||||
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()))
|
||||
if (obj.getCallback(0) != null && obj.getCallback(0) != ProxyDispatcher) {
|
||||
return (obj.getCallback(0) as ProxyInterceptor).container
|
||||
}
|
||||
return (obj.getCallback(0) as ProxyInterceptor).container
|
||||
|
||||
obj.setCallback(0, ProxyInterceptor(container))
|
||||
return container
|
||||
}
|
||||
|
||||
fun <T> getCachedTarget(clazz: Class<T>): Class<T> = cache.computeIfAbsent(clazz) {
|
||||
fun <T : Any> getCachedTarget(clazz: Class<T>): Class<T> = cache.computeIfAbsent(clazz) {
|
||||
newEnhancer(clazz).createClass()
|
||||
}.uncheckedCast()
|
||||
}
|
||||
|
@ -3,65 +3,40 @@ package cn.tursom.proxy
|
||||
import cn.tursom.proxy.annotation.ForEachProxy
|
||||
import cn.tursom.proxy.annotation.ForFirstProxy
|
||||
import cn.tursom.reflect.asm.ReflectAsmUtils
|
||||
import com.esotericsoftware.reflectasm.MethodAccess
|
||||
import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal typealias ProxyMethodHandler = (proxy: ProxyMethod, args: Array<out Any?>) -> ProxyResult<*>
|
||||
|
||||
interface ProxyMethod {
|
||||
@Throws(Throwable::class)
|
||||
fun onProxy(obj: Any, c: ProxyContainer, method: Method, args: Array<out Any?>, proxy: MethodProxy): ProxyResult<*> {
|
||||
fun onProxy(
|
||||
ignored: Any,
|
||||
c: ProxyContainer,
|
||||
method: Method,
|
||||
args: Array<out Any?>,
|
||||
proxy: MethodProxy
|
||||
): ProxyResult<*> {
|
||||
val handlerCacheMap = getHandlerCacheMap(javaClass)
|
||||
val methodResult = handlerCacheMap[method]
|
||||
if (methodResult != null) {
|
||||
return if (methodResult.success) {
|
||||
methodResult.result(this, args)
|
||||
val handlerCache = handlerCacheMap[method]
|
||||
if (handlerCache != null) {
|
||||
return if (handlerCache.success) {
|
||||
handlerCache.result(this, args)
|
||||
} else {
|
||||
ProxyResult.failed<Any>()
|
||||
}
|
||||
}
|
||||
|
||||
val reflectAsmMethod = try {
|
||||
ReflectAsmUtils.getMethod(
|
||||
javaClass,
|
||||
method.name,
|
||||
paramTypes = method.parameterTypes,
|
||||
returnType = method.returnType,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
if (reflectAsmMethod != null) {
|
||||
val (methodAccess, index) = reflectAsmMethod
|
||||
handlerCacheMap[method] = ProxyResult({ p, a ->
|
||||
ProxyResult.of(methodAccess.invoke(p, index, *a))
|
||||
}, true)
|
||||
return ProxyResult.of(methodAccess.invoke(this, index, *args))
|
||||
val reflectAsmHandler = ReflectASMProxyMethodInvoker[this, method, handlerCacheMap]
|
||||
if (reflectAsmHandler != null) {
|
||||
return reflectAsmHandler(this, args)
|
||||
}
|
||||
|
||||
val selfMethod: Method
|
||||
try {
|
||||
var methodName = method.name
|
||||
for (annotation in method.annotations) {
|
||||
if (annotation is ForEachProxy) {
|
||||
if (annotation.name.isNotEmpty()) {
|
||||
methodName = annotation.name
|
||||
break
|
||||
}
|
||||
} else if (annotation is ForFirstProxy) {
|
||||
if (annotation.name.isNotEmpty()) {
|
||||
methodName = annotation.name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
selfMethod = javaClass.getMethod(methodName, *method.parameterTypes)
|
||||
selfMethod.isAccessible = true
|
||||
handlerCacheMap[method] = ProxyResult({ p, a ->
|
||||
ProxyResult.of(selfMethod(p, *a))
|
||||
}, true)
|
||||
return ProxyResult.of<Any>(selfMethod(this, *args))
|
||||
} catch (_: Exception) {
|
||||
val javaReflectHandler = JavaReflectProxyMethodInvoker[this, method, handlerCacheMap]
|
||||
if (javaReflectHandler != null) {
|
||||
javaReflectHandler(this, args)
|
||||
}
|
||||
|
||||
handlerCacheMap[method] = ProxyResult.failed()
|
||||
@ -71,10 +46,10 @@ interface ProxyMethod {
|
||||
companion object {
|
||||
private val handlerCacheMapMap: MutableMap<
|
||||
Class<out ProxyMethod>,
|
||||
MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> ProxyResult<*>>>> =
|
||||
HashMap()
|
||||
MutableMap<Method, ProxyResult<ProxyMethodHandler>>
|
||||
> = HashMap()
|
||||
|
||||
fun getHandlerCacheMap(type: Class<out ProxyMethod>): MutableMap<Method, ProxyResult<(proxy: ProxyMethod, args: Array<out Any?>) -> ProxyResult<*>>> {
|
||||
fun getHandlerCacheMap(type: Class<out ProxyMethod>): MutableMap<Method, ProxyResult<ProxyMethodHandler>> {
|
||||
var handlerCacheMap = handlerCacheMapMap[type]
|
||||
if (handlerCacheMap == null) synchronized(handlerCacheMapMap) {
|
||||
handlerCacheMap = handlerCacheMapMap[type]
|
||||
@ -86,4 +61,90 @@ interface ProxyMethod {
|
||||
return handlerCacheMap!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReflectASMProxyMethodInvoker(
|
||||
val methodAccess: MethodAccess,
|
||||
val index: Int,
|
||||
) : ProxyMethodHandler {
|
||||
companion object {
|
||||
private val fastInvoker: MethodAccess.(Any, Int, Array<out Any?>) -> Any? = MethodAccess::invoke
|
||||
|
||||
operator fun get(
|
||||
proxy: ProxyMethod,
|
||||
method: Method,
|
||||
handlerCacheMap: MutableMap<Method, ProxyResult<ProxyMethodHandler>>
|
||||
): ProxyMethodHandler? {
|
||||
val reflectAsmMethod = try {
|
||||
ReflectAsmUtils.getMethod(
|
||||
proxy.javaClass,
|
||||
method.name,
|
||||
paramTypes = method.parameterTypes,
|
||||
returnType = method.returnType,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
if (reflectAsmMethod != null) {
|
||||
val (methodAccess, index) = reflectAsmMethod
|
||||
val invoker = ReflectASMProxyMethodInvoker(methodAccess, index)
|
||||
handlerCacheMap[method] = ProxyResult.of(invoker)
|
||||
return invoker
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(proxy: ProxyMethod, args: Array<out Any?>): ProxyResult<*> {
|
||||
return ProxyResult.of(fastInvoker(methodAccess, proxy, index, args))
|
||||
}
|
||||
}
|
||||
|
||||
private class JavaReflectProxyMethodInvoker(
|
||||
val method: Method,
|
||||
) : ProxyMethodHandler {
|
||||
companion object {
|
||||
private val fastInvoker: Method.(Any, Array<out Any?>) -> Any? = Method::invoke
|
||||
|
||||
operator fun get(
|
||||
proxy: ProxyMethod,
|
||||
method: Method,
|
||||
handlerCacheMap: MutableMap<Method, ProxyResult<ProxyMethodHandler>>
|
||||
): ProxyMethodHandler? {
|
||||
var invoker: ProxyMethodHandler? = null
|
||||
|
||||
val selfMethod: Method
|
||||
try {
|
||||
var methodName = method.name
|
||||
for (annotation in method.annotations) {
|
||||
if (annotation is ForEachProxy) {
|
||||
if (annotation.name.isNotEmpty()) {
|
||||
methodName = annotation.name
|
||||
break
|
||||
}
|
||||
} else if (annotation is ForFirstProxy) {
|
||||
if (annotation.name.isNotEmpty()) {
|
||||
methodName = annotation.name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
selfMethod = proxy.javaClass.getMethod(methodName, *method.parameterTypes)
|
||||
selfMethod.isAccessible = true
|
||||
|
||||
invoker = JavaReflectProxyMethodInvoker(method)
|
||||
|
||||
handlerCacheMap[method] = ProxyResult(invoker, true)
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
|
||||
return invoker
|
||||
}
|
||||
}
|
||||
|
||||
override fun invoke(proxy: ProxyMethod, args: Array<out Any?>): ProxyResult<*> {
|
||||
return ProxyResult.of(fastInvoker(method, proxy, args))
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,13 @@ import net.sf.cglib.proxy.MethodProxy
|
||||
import java.lang.reflect.Method
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
typealias ProxyMethodCacheFunction = (obj: Any, c: ProxyContainer, 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(
|
||||
private var lastModify: Long = 0,
|
||||
@ -16,6 +22,10 @@ class ProxyMethodCache(
|
||||
private val functionMap = ConcurrentHashMap<MethodProxy, ProxyMethodCacheFunction>()
|
||||
|
||||
fun update(lastModify: Long, proxy: MethodProxy, function: ProxyMethodCacheFunction = functionMap[proxy] ?: failed) {
|
||||
if (this.lastModify != lastModify) {
|
||||
functionMap.clear()
|
||||
}
|
||||
|
||||
this.lastModify = lastModify
|
||||
functionMap[proxy] = function
|
||||
}
|
||||
@ -30,6 +40,6 @@ class ProxyMethodCache(
|
||||
): ProxyResult<*>? = if (lastModify != this.lastModify) {
|
||||
null
|
||||
} else {
|
||||
(functionMap[proxy] ?: failed)(obj, c, method, args, proxy)
|
||||
functionMap[proxy]?.invoke(obj, c, method, args, proxy)
|
||||
}
|
||||
}
|
@ -5,13 +5,18 @@ import cn.tursom.core.uncheckedCast
|
||||
data class ProxyResult<out R>(
|
||||
val result: R,
|
||||
val success: Boolean = false,
|
||||
val cache: Boolean = true,
|
||||
) {
|
||||
companion object {
|
||||
val success: ProxyResult<*> = ProxyResult<Any?>(null, true)
|
||||
val failed: ProxyResult<*> = ProxyResult<Any?>(null, false)
|
||||
|
||||
fun <R> of(): ProxyResult<R?> = success.uncheckedCast()
|
||||
fun <R> of(result: R): ProxyResult<R> = ProxyResult(result, true)
|
||||
fun <R> of(result: R): ProxyResult<R> = if (result == null) {
|
||||
success.uncheckedCast()
|
||||
} else {
|
||||
ProxyResult(result, true)
|
||||
}
|
||||
|
||||
fun <R> failed(): ProxyResult<R> = failed.uncheckedCast()
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ object ProxyRunner {
|
||||
val result = container.forFirstProxy { p ->
|
||||
if (classes.isEmpty() || classes.stream().anyMatch { c: Class<*> -> c.isInstance(p) }) {
|
||||
val result = p.onProxy(obj, container, method, args, proxy)
|
||||
if (forFirstProxy.cache && result.success && result.cache) {
|
||||
if (forFirstProxy.cache && result.success) {
|
||||
container.context[proxyMethodCacheKey].update(container.lastModify, proxy, p::onProxy)
|
||||
}
|
||||
return@forFirstProxy result
|
||||
|
Loading…
Reference in New Issue
Block a user