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();
}
@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.