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

io.github.qy8502.jetcacheplus.JetCacheDubboProxyFactoryWrapper Maven / Gradle / Ivy

package io.github.qy8502.jetcacheplus;

import com.alicp.jetcache.anno.Cached;
import com.alicp.jetcache.anno.aop.CacheAdvisor;
import com.alicp.jetcache.anno.aop.CachePointcut;
import com.alicp.jetcache.anno.aop.JetCacheInterceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.RpcException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.context.ApplicationContext;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


public class JetCacheDubboProxyFactoryWrapper implements ProxyFactory {
    private static final long serialVersionUID = -3748439745014166871L;
    private static final Logger logger = LoggerFactory.getLogger(JetCacheDubboProxyFactoryWrapper.class);

    private final ProxyFactory proxyFactory;

    public JetCacheDubboProxyFactoryWrapper(ProxyFactory proxyFactory) {
        this.proxyFactory = proxyFactory;
    }

    public CacheAdvisor cacheAdvisor;
    public JetCacheInterceptor jetCacheInterceptor;
    public static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext applicationContext) {
        JetCacheDubboProxyFactoryWrapper.applicationContext = applicationContext;
    }

    protected CacheAdvisor getCacheAdvisor() {
        if (cacheAdvisor == null) {
            cacheAdvisor = applicationContext.getBean(CacheAdvisor.class);
        }
        return cacheAdvisor;
    }

    protected CachePointcut getCachePointcut() {
        return (CachePointcut) getCacheAdvisor().getPointcut();
    }

    protected JetCacheInterceptor getJetCacheInterceptor() {
        if (jetCacheInterceptor == null) {
            jetCacheInterceptor = applicationContext.getBean(JetCacheInterceptor.class);
        }
        return jetCacheInterceptor;
    }

    @Override
    public  T getProxy(Invoker invoker, boolean generic) throws RpcException {
        T dubboProxy = proxyFactory.getProxy(invoker, generic);
        CachePointcut cachePointcut = getCachePointcut();
        Class serviceInterface = invoker.getInterface();

        org.springframework.aop.framework.ProxyFactory defaultProxyFactory = new org.springframework.aop.framework.ProxyFactory();
        defaultProxyFactory.setInterfaces(serviceInterface);
        defaultProxyFactory.addAdvisor(new DefaultPointcutAdvisor(
                new StaticMethodMatcherPointcut() {
                    @Override
                    public boolean matches(Method method, Class targetClass) {
                        return (method.isDefault() && method.getAnnotation(Cached.class) != null);
                    }
                },
                new MethodInterceptor() {
                    Map methodHandleMap = new HashMap<>();
                    String interfaceName = serviceInterface.getSimpleName();

                    @Override
                    public Object invoke(MethodInvocation invocation) throws Throwable {
                        MethodHandle methodHandle = methodHandleMap.computeIfAbsent(invocation.getMethod(), method -> {
                            try {
                                Constructor constructor = null;
                                constructor = MethodHandles.Lookup.class
                                        .getDeclaredConstructor(Class.class);
                                constructor.setAccessible(true);
                                return constructor.newInstance(method.getDeclaringClass())
                                        .in(method.getDeclaringClass())
                                        .unreflectSpecial(method, method.getDeclaringClass())
                                        .bindTo(dubboProxy);
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        });
                        logger.debug("JETCACHE_PLUS_DUBBO -> invoke interface default method '{}.{}'", interfaceName, invocation.getMethod().getName());
                        return methodHandle.invokeWithArguments(invocation.getArguments());
                    }
                }));
        defaultProxyFactory.setTarget(dubboProxy);
        T defaultProxy = (T) defaultProxyFactory.getProxy();

        org.springframework.aop.framework.ProxyFactory cacheProxyFactory = new org.springframework.aop.framework.ProxyFactory();
        cacheProxyFactory.setInterfaces(serviceInterface);
        //cacheProxyFactory.addAdvice(getJetCacheInterceptor());
        cacheProxyFactory.addAdvisor(new DefaultPointcutAdvisor(
                new StaticMethodMatcherPointcut() {
                    @Override
                    public boolean matches(Method method, Class targetClass) {
                        return cachePointcut.matches(method, targetClass) && method.getAnnotation(Cached.class) != null;
                    }
                },
                getJetCacheInterceptor()));
        cacheProxyFactory.setTarget(defaultProxy);
        T cacheProxy = (T) cacheProxyFactory.getProxy();
        return AopUtils.canApply(cachePointcut, cacheProxy.getClass()) ? cacheProxy : dubboProxy;
    }

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public  T getProxy(Invoker invoker) throws RpcException {
        return getProxy(invoker, false);
    }

    @Override
    public  Invoker getInvoker(T proxy, Class type, URL url) throws RpcException {
        return proxyFactory.getInvoker(proxy, type, url);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy