我正在尝试使用Spring AOP拦截Feign.Client
调用并记录对Splunk Server的请求和响应。我的项目包中的所有方法均按我的预期被拦截,但Feign.Client
未被拦截。
这是我的AOP课:
@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();
}
}
如我所料,方法myAroundDemo
被多次调用,但从未调用myAroundFeign
。
我有一个简单的Controller调用我的接口(Feign API),这就是控制器:
@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";
}
}
这是我的伪装界面:
@FeignClient(url = "http://localhost:3000", name = "feign", configuration = FeignConfig.class)
public interface ExternalAPI {
@GetMapping(value = "/menu")
String listUsers();
}
答案 0 :(得分:1)
Spring AOP仅适用于Spring组件。我的猜测是它不起作用,因为Feign不是Spring组件,因此超出了Spring AOP的范围。如果您需要将方面应用于非Spring类,则只需使用完整的AspectJ。 Spring手册介绍了如何configure it via LTW (load-time weaving)。
答案 1 :(得分:1)
@kriegaex是正确的,我不能在非Spring组件中应用AOP。但是我不想使用纯粹的AspectJ,所以我使用了另一个解决方案。这是我解决问题的步骤:
1)启用Spring Cloud Ribbon我获得了由LoadBalancerFeignClient
的spring管理的类feign.Client
,因此我在pom.xml中添加了依赖项并更改了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)在MyAspect
类中,我拦截了LoadBalancerFeignClient
类:
@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;
}
现在效果很好,我得到了我需要的所有信息。
答案 2 :(得分:0)
我也面临这个问题。但是我无法截获LoadBalancerFeignClient类。我使用相同的代码进行测试,但无法正常工作。enter image description here
当我调试功能时,我发现(指向)TraceLoadBalanceFeignClient。LoadBalancerFeignClient的子类。最后我发现使用侦探功能时。假冒客户将由sleuth的feignbuilder创建。切入点将无效
答案 3 :(得分:0)
Feign内置了无需AOP即可使用的日志记录。如果创建feign.Logger
实例并进行注册,它将记录请求,响应和标头。
@Bean
public feign.Logger logger() {
/* requires feign-slf4j */
return new Slf4jLogger();
}
Logger
实例提供以下功能:
如果只需要日志记录,这可能是一个更好的解决方案。