Search code examples
aopspring-aopspring-cloud-feignfeign

Spring AOP does not intercept Feign.Client calls


I'm trying to use Spring AOP to intercept Feign.Client calls and log request and response to my Splunk Server. All methods in my project package are intercepted as I expected but Feign.Client doesn't.

This is my AOP class:

@Component
@Aspect
public class MyAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(* com.example.demo.*.*(..))")
    public void pointCutDemo(){}

    @Pointcut("execution(* feign.Client+.*(..))")
    public void pointCutFeign(){}

    @Around("pointCutDemo()")
    public void myAroundDemo(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("calling joinpoint "+joinPoint.getSignature().getName());
        joinPoint.proceed();
    }

    @Around("pointCutFeign()")
    public void myAroundFeign(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("calling feign joinpoint "+joinPoint.getSignature().getName());
        joinPoint.proceed();
    }
}

The method myAroundDemo is called multiple times, as I expected, but myAroundFeign is never called.

I have a simple Controller that call my interface (Feign API), this is the controller:

@RestController
public class Controller {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ExternalAPI externalAPI;

    @GetMapping
    public String get(){
        logger.info("calling get method");
        logger.info(String.valueOf(externalAPI.listUsers()));
        return "I'm here";
    }
}

And this is my Feign Interface:

@FeignClient(url = "http://localhost:3000", name = "feign", configuration = FeignConfig.class)
public interface ExternalAPI {
    @GetMapping(value = "/menu")
    String listUsers();
}

Solution

  • @kriegaex is correct and I can't apply AOP in a non-Spring Component. But I prefer not to use pure AspectJ, so I fixed with another solution. Here are my steps to solve the problem:

    1) Enabling Spring Cloud Ribbon I got the class LoadBalancerFeignClient managed by spring that implements feign.Client, so I added the dependency in pom.xml and changed my application.yml.

    application.yml

    myfeign:
      ribbon:
        listOfServers: localhost:3000
    

    pom.xml

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    

    2) In MyAspect class I intercepted the LoadBalancerFeignClient class:

    @Pointcut("execution(* org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(..))")
    public void pointCutFeign(){}
    
    @Around("pointCutFeign()")
    public Object myAroundFeign(ProceedingJoinPoint joinPoint) throws Throwable {
        if (joinPoint.getArgs().length > 0) {
            Request request = (Request) joinPoint.getArgs()[0];
            logger.info("REQUEST >>>>>>>>>>>>");
            logger.info("URL = "+request.url());
            logger.info("METHOD = "+request.httpMethod().name());
            logger.info("BODY = "+request.requestBody().asString());
            logger.info("HEADERS = "+request.headers().toString());
        }
    
        Response response = (Response) joinPoint.proceed();
    
        logger.info("RESPONSE <<<<<<<<<<<<<<");
        logger.info("STATUS = "+response.status());
        logger.info("HEADERS = "+response.headers().toString());
        logger.info("BODY = " + IOUtils.toString(response.body().asInputStream(), "UTF-8"));
        return response;
    }
    

    Now it works very well, i got all information that i need.