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

com.tairanchina.csp.dew.jdbc.proxy.MethodProxy Maven / Gradle / Ivy

package com.tairanchina.csp.dew.jdbc.proxy;

import com.tairanchina.csp.dew.Dew;
import com.tairanchina.csp.dew.jdbc.DewDS;
import com.tairanchina.csp.dew.jdbc.DewDao;
import com.tairanchina.csp.dew.jdbc.annotations.Select;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.util.ConcurrentReferenceHashMap;

import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;


public class MethodProxy implements InvocationHandler {

    private static final Map METHOD_HANDLE_CACHE = new ConcurrentReferenceHashMap<>(10, ConcurrentReferenceHashMap.ReferenceType.SOFT);

    private static final Map REL_DAO_DS = new ConcurrentReferenceHashMap<>(10, ConcurrentReferenceHashMap.ReferenceType.SOFT);

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String dsName = getRelDAOAndDS(method.getDeclaringClass(), proxy);
        if (!method.getDeclaringClass().isInterface() && !method.isDefault()) {
            // This proxy is class and method has not impl
            return method.invoke(this, args);
        } else if (method.isDefault()) {
            // This proxy is interface but method has impl
            return getMethodHandle(method).bindTo(proxy)
                    .invokeWithArguments(args);
        } else {
            // This proxy is interface
            return run(method, args, dsName);
        }
    }

    private String getRelDAOAndDS(Class clazz, Object proxy) throws Throwable {
        if (clazz == DewDao.class) {
            return "";
        }
        String dsName = REL_DAO_DS.getOrDefault(clazz, null);
        if (dsName != null) {
            return dsName;
        }
        Method dsMethod = clazz.getMethod("ds");
        if (!clazz.isInterface() && !dsMethod.isDefault()) {
            // This proxy is class and method has not impl
            dsName = (String) dsMethod.invoke(this);
        } else if (dsMethod.isDefault()) {
            // This proxy is interface but method has impl
            dsName = (String) getMethodHandle(dsMethod).bindTo(proxy).invokeWithArguments();
        }
        REL_DAO_DS.put(clazz, dsName);
        return dsName;
    }


    private MethodHandle getMethodHandle(Method method) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        MethodHandle handle = METHOD_HANDLE_CACHE.get(method);
        if (handle == null) {
            final Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
            if (!constructor.isAccessible()) {
                constructor.setAccessible(true);
            }
            final Class declaringClass = method.getDeclaringClass();
            handle = constructor.newInstance(declaringClass)
                    .unreflectSpecial(method, declaringClass);
            METHOD_HANDLE_CACHE.put(method, handle);
        }
        return handle;
    }

    /**
     * 实现接口的核心方法
     */
    public Object run(Method m, Object[] args, String dsName) {
        MethodConstruction method = new MethodConstruction(m, args);
        for (Annotation annotation : method.getMethodAnnotations()) {
            if (annotation instanceof Select) {
                if (method.flagOfPaging()) {
                    return ((DewDS) Dew.ds(dsName)).selectForPaging(((Select) annotation).entityClass(), method, ((Select) annotation).value());
                }
                List list = ((DewDS) Dew.ds(dsName)).selectForList(((Select) annotation).entityClass(), method.getParamsMap(), ((Select) annotation).value());
                if (!method.getReturnType().isAssignableFrom(List.class)) {
                    return !list.isEmpty() ? list.get(0) : null;
                }
                return list;
            }
        }
        return null;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy