All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fun.langel.cql.bind.CaveProxy Maven / Gradle / Ivy

The newest version!
package fun.langel.cql.bind;

import fun.langel.cql.spring.Configuration;

import java.io.Serializable;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;

/**
 * @author [email protected](GuHan)
 * @since 2021/10/19 8:53 下午
 **/
public class CaveProxy implements InvocationHandler, Serializable {

    private final Class klass;
    private final Map cache;

    private final Configuration configuration;

    public CaveProxy(final Configuration configuration,
                     final Class interfaceKlass,
                     final Map cache) {
        this.configuration = configuration;
        this.klass = interfaceKlass;
        this.cache = cache;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        } else if (isDefaultMethod(method)) {
            return invokeDefaultMethod(proxy, method, args);
        }
        return cachedMethod(method).execute(args);
    }

    public CaveMethod cachedMethod(final Method method) {
        return cache.computeIfAbsent(method, (m) -> new CaveMethod(this.configuration, this.klass, m));
    }

    public Object invokeDefaultMethod(Object proxy, Method method, Object... args) throws Throwable {
        final Constructor constructor = MethodHandles.Lookup.class
                .getDeclaredConstructor(Class.class, int.class);
        if (!constructor.isAccessible()) {
            constructor.setAccessible(true);
        }
        final Class declaringClass = method.getDeclaringClass();
        return constructor
                .newInstance(declaringClass,
                        MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
                                | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC)
                .unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
    }

    public boolean isDefaultMethod(final Method method) {
        return (method.getModifiers()
                & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC
                && method.getDeclaringClass().isInterface();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy