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程序启动时,过程中分为几个阶段,每进行一个阶段,发出一个事件,依次对应ApplicationStartingEvent到ApplicationReadyEvent。标志着Application从启动开始到启动完成,各个阶段的分割点。参考Spring启动过程...
使用场景在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进行操作。用法本文以在Spring boot下的使用为例来进行说明。首先,需要实现ApplicationListener接口并实现onApplicationEvent方法。把需要处理的操作放在onAppl
Spring容器初始化完毕后,调用BeanPostProcessor这个类,这个类实现ApplicationListener接口,重写onApplicationEvent方法,
方法中就是我们自己要在容器初始化完毕后载入的数据或者缓存。
以下是XML配置:
以下是自己写的BeanPostProcessor类:
以下是启动Tomcat后。反复载入了数据,调用了两次on...