Spring cloud 或者 Spring boot项目中,使用FeignClient 实现客户端调用。项目中有通过ApplicationListener初始化的方法。

@Component
@Slf4j
public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("--------- 执行 监听器,event:{}",event.getApplicationContext().getDisplayName());
  • 项目启动时,ApplicationListener.onApplicationEvent() 执行两次。
  • FeignClient第一次调用超时,也会触发执行ApplicationListener.onApplicationEvent() 。
  • 调用服务异常时,触发ApplicationListener.onApplicationEvent()执行一次。

通过debug 代码,发现启动时执行的两次,第一次的事件是 FeignContext :

 第二次执行:

事件是spring boot启动加载事件

 服务接口调用异常,触发fallback 熔断器时,也会执行:

github上有人提交issues:https://github.com/spring-cloud/spring-cloud-openfeign/issues/119

但到目前还没有解决该bug.

可是换做其他启动init方式,spring boot 还可以使用以下方式初始化,避免与Feign 冲突。

@Component
@Slf4j
public class MyPostConstruct {
    @Value("${spring.application.name}")
    private String name;
    @PostConstruct
    private void init() {
        log.info("appName:{}",name);

注意:使用方法一时,不能同时使用@ConfigurationProperties 注解,否则也会导致加载两次。

@Component
@Slf4j
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("MyApplicationRunner run...");
@Component
@Slf4j
public class MyCommandLineRunner implements CommandLineRunner {
    @Value("${spring.application.name}")
    private String name;
    @Override
    public void run(String... args) throws Exception {
        log.info("MyStartRunner run...,appName:{}",name);

以上三种方式,都不会出现启动加载两次的现象。

如果必须要使用ApplicationListener方式,可以使用以下方式,避免重复加载:

@Component
@Slf4j
public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("--------- 执行 监听器,event:{}",event.getApplicationContext().getDisplayName());
        String displayName = event.getApplicationContext().getDisplayName();
        if(displayName.contains("FeignContext") || displayName.contains("SpringClientFactory")) {
            return;
        //todo semo code

关于第一次访问超时的问题,目前没有太好的解决方式,只能是配置较长的超时时间。

配置如下:

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 60000
feign:
  hystrix:
    enabled: true
  ribbon:
    warmup: true
ribbon:
  ConnectTimeout: 20000
  ReadTimeout: 20000
原文地址:http://www.cnblogs.com/a757956132/p/5039438.html 在做web项目开发中,尤其是企业级应用开发的时候,往往会在工程启动的时候做许多的前置检查。   比如检查是否使用了我们组禁止使用的Mysql的group_concat函数,如果使用了项目就不能启动,并指出哪个文件的xml文件使用了这个函数。 而在Spring的web项目中,我们可... 1、一些比较独立,内容小巧的初始化逻辑,不影响springboot启动速度的使用@postConstruct注解2、若想通过ApplicationListener事件监听的方式,则需要处理好指定的容器、3、在数据初始化层面,不推荐@PostConstruct和ApplicationListener,原因是两者都会影响程序的启动,如果执行逻辑耗时很长,启动服务时间就很长。 public void onApplicationEvent(ContextRefreshedEvent event) { try { if(event.getApplicationContext().getParent()==null){ //root application context 没有parent,他就是老大. el... onApplicationEvent调用了2次,3次,多次 解决方案 首先,被执行这么多次,肯定是自己配置的问题,我以spring boot为例来说 我也遇到了执行三次,排查后发现一个是spring boot的,另外两个是自己配的,所以才导致三次,理论上可以导致n次的 三个事件源分别为: spring boot 自带的注解形式上下文(解析所有通过开放端口发来的请求) org.springfra... 问题:最近刚开始使用openfeign,发现一次get请求,在请求的失败的时候,消费者会收到两次的请求。但是发送端明明只发送了一次请求。根据报错的代码定位不太容易定位到源码重试的位置。之前一直错误的把问题原因归结到了是重试的配置出现错误,在配置文件,代码的配置,拦截器等多个问题点进行了找原因,最后都没有解决。最不可思议的是,我关掉了系统中的重试,但是这个重试的场景依旧在。后来终于在网上看到了 参考中的帖子,定位到了源码中重试的原因。总结:请求失败的情况下,如果不是get请求,只能请求一次。而get请求再失败 applicationontext和使用MVC之后的webApplicationontext会两次调用上面的方法,如何区分这个两种容器呢? 但是这个时候,会存在一个问题,在web 项目中(spring mvc),系统会存在两个容器,一个是root application context ,另一个就是我们自己的 projectName-servlet context(作为root applicat... Spring容器初始化完成后,调用BeanPostProcessor这个类,这个类实现ApplicationListener接口,重写onApplicationEvent方法, 方法中就是我们自己要在容器初始化完成后加载的数据或者缓存。 下面是XML配置: 下面是自己写的BeanPostProcessor类: 下面是启动Tomcat后,重复加载了数据,调用了两次onAppl 一、case复现事件定义 Java代码  public class MyEvent extends ApplicationEvent {        public MyEvent(Object object) {          super(object);      }  }    监听定义 Java代码  @Component  public class MyListener implem... 我们知道Spring有两大类事件,一类是Application事件,超类是SpringApplicationEvent,这类事件是在Spring程序启动时,过程中分为几个阶段,每进行一个阶段,发出一个事件,依次对应ApplicationStartingEventApplicationReadyEvent。标志着Application从启动开始到启动完成,各个阶段的分割点。参考Spring启动过程... 使用场景在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进行操作。用法本文以在Spring boot下的使用为例来进行说明。首先,需要实现ApplicationListener接口并实现onApplicationEvent方法。把需要处理的操作放在onAppl Spring容器初始化完毕后,调用BeanPostProcessor这个类,这个类实现ApplicationListener接口,重写onApplicationEvent方法, 方法中就是我们自己要在容器初始化完毕后载入的数据或者缓存。 以下是XML配置: 以下是自己写的BeanPostProcessor类: 以下是启动Tomcat后。反复载入了数据,调用了两次on...