Я пытаюсь использовать Spring AOP для перехвата вызовов Feign.Client
и регистрации запросов и ответов на моем сервере Splunk. Все методы в моем пакете проекта перехватываются, как я и ожидал, но Feign.Client
нет.
Это мой класс АОП:
@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
никогда не вызывается.
У меня есть простой контроллер, который вызывает мой интерфейс (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";
}
}
А это мой интерфейс Feign:
@FeignClient(url = "http://localhost:3000", name = "feign", configuration = FeignConfig.class)
public interface ExternalAPI {
@GetMapping(value = "/menu")
String listUsers();
}
Spring AOP применяется только к компонентам Spring. Я предполагаю, что это не работает, потому что Feign не является компонентом Spring и, следовательно, выходит за рамки Spring AOP. Если вам нужно применить аспекты к классам, отличным от Spring, просто используйте полный AspectJ. Руководство Spring объясняет, как настроить через LTW (load-time weaving).
@kriegaex верен, и я не могу применить АОП в компоненте, отличном от Spring. Но я предпочитаю не использовать чистый AspectJ, поэтому исправил другим решением. Вот мои шаги для решения проблемы:
1) Включение Spring Cloud Ribbon Я получил класс LoadBalancerFeignClient
, управляемый Spring, который реализует feign.Client
, поэтому я добавил зависимость в pom.xml и изменил свой application.yml.
приложение.yml
myfeign:
ribbon:
listOfServers: localhost:3000
пом.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;
}
Теперь это работает очень хорошо, я получил всю информацию, которая мне нужна.
Следуя вашему ответу, я работал над той же проблемой для ведения журнала. Однако, когда я пытаюсь использовать возвращаемое значение метода listUsers()
из вашего примера, я получаю нулевое значение, хотя совет получает объект ответа. Любые идеи по этому поводу? @Роналдо
Я тоже сталкиваюсь с этим вопросом. но я не могу перехватить класс LoadBalancerFeignClient. я использую тот же код для проверки, но он не работает.введите описание изображения здесь
когда я отлаживаю функцию, я нахожу (эту) точку на TraceLoadBalanceFeignClient. Подкласс LoadBalancerFeignClient. Наконец, я нахожу, когда использую сыщика. клиент feign будет создан с помощью feignbuilder sleuth. Pointcut будет недействительным
Проверьте, используете ли вы правильные зависимости в файле pom.xml для активного весеннего aop abd и включили ли ленту в свойствах весны.
причина в сыщике. если я удалю сыщика из своего проекта, класс LoadBalancerFeignClient может быть перехвачен.
В Feign встроено ведение журнала, которое можно использовать без АОП. Если вы создадите экземпляр feign.Logger
и зарегистрируете его, он будет регистрировать запрос, ответ и заголовки.
@Bean
public feign.Logger logger() {
/* requires feign-slf4j */
return new Slf4jLogger();
}
Logger
экземпляры предоставляют следующие функции:
Это может быть лучшим решением, если ведение журнала — это все, что вам нужно.
Очень приятно, что вы нашли это простое решение для себя. В общем, мы можем сказать, что если вы хотите избежать AspectJ, у вас есть возможность написать оболочку компонента Spring вокруг любых объектов третьего класса, которые вы хотите перехватить. В вашем случае уже был готовый компонент, что сделало его еще проще. :-) Кстати, вы должны принять свой ответ, чтобы закрыть этот вопрос.