I wish there was out-of-the-box support for @Cacheable on feign clients.

Here's how I made it work:

import feign.Capability;
import feign.InvocationHandlerFactory;
import feign.InvocationHandlerFactory.MethodHandler;
import feign.Target;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cache.interceptor.CacheInterceptor;
import org.springframework.stereotype.Component;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.Map;

import static java.util.stream.Collectors.toMap;

/**
 * Allows Spring's @Cache* annotations to be declared on the feign client's methods
 */
@Component
public class CachingCapability implements Capability {
    private final CacheInterceptor cacheInterceptor;

    public CachingCapability(CacheInterceptor cacheInterceptor) {
        this.cacheInterceptor = cacheInterceptor;
    }

    @Override
    public InvocationHandlerFactory enrich(InvocationHandlerFactory invocationHandlerFactory) {
        return (target, dispatch) -> invocationHandlerFactory.create(target, withCacheProxy(target, dispatch));
    }

    private Map<Method, MethodHandler> withCacheProxy(Target<?> target, Map<Method, MethodHandler> dispatch) {
        return dispatch.entrySet().stream()
                .map(e -> Map.entry(e.getKey(), (MethodHandler) argv -> cacheInterceptor.invoke(new MethodInvocation() {
                    @Override
                    public Method getMethod() {
                        return e.getKey();
                    }

                    @Override
                    public Object[] getArguments() {
                        return argv;
                    }

                    @Override
                    public Object proceed() throws Throwable {
                        return e.getValue().invoke(argv);
                    }

                    @Override
                    public Object getThis() {
                        return target;
                    }

                    @Override
                    public AccessibleObject getStaticPart() {
                        return e.getKey();
                    }
                }))).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
    }
}

Also see: https://github.com/OpenFeign/feign/issues/1513