@mercyblitz Thanks for take a look at this. I'm a reader of your book 
《SpringBoot编程思想》.
To be honest, your solutions is not easy to achieve.

Dubbo `@Service` Bean is not registered by child context created by Feign. The 
child context sets its parent context to which `ApplicationContextAware` will 
set to. We can do nothing to prevent the `ContextRefreshedEvent` received by 
`ServiceBean`. Because the event is also published to parent context by 
`AbstractApplicationContext`.

To see the event and source published by feign, it's easy to implement a 
EventListener `ApplicationListener<ContextRefreshedEvent>`

```
@Component
public class FakeListener implements 
ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {
  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) 
throws BeansException {
    this.applicationContext = applicationContext;
  }

  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
    ApplicationContext eventApplicationContext = event.getApplicationContext();

    if 
(applicationContext.getClass().equals(eventApplicationContext.getClass())) {
      //Here is the right opportunity that Spring beans are ready.
    }
....
}
```

If we print the `ContextRefreshedEvent`'s class name and its parent class name.
We will see like this:
```
//Published by Feign
 :  
org.springframework.context.annotation.AnnotationConfigApplicationContext@2cc3b0a7
  FeignContext-XXXXXXXX
 : ----- application-1  
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2c1b9e4b
 : ---------- bootstrap  
org.springframework.context.annotation.AnnotationConfigApplicationContext@27adc16e


//Published by Spring when all Beans are ready
 :  application-1  
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2c1b9e4b
 : ----- bootstrap  
org.springframework.context.annotation.AnnotationConfigApplicationContext@27adc16e

```

Whatever the `ApplicationContext` class is, the right one is setted by 
`ApplicationContextAware` .
So the right way to fix this, is to let `ServiceBean` listen the Event 
published by right context. 

And there is a advantage for checking what `ApplicationContext` we really want, 
to make it invoked only once.

My advice is to change the `ServiceBean` code:
```
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (!isExported() && !isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + 
getInterface());
            }
            ApplicationContext eventApplicationContext = 
event.getApplicationContext();
           if 
(applicationContext.getClass().equals(eventApplicationContext.getClass())) {
               export();//Here is the right opportunity that Spring beans are 
ready.
           }
          
        }
    }
```

**To those who meets this issue urgently**. When dubbo provider depends on a 
FeignClient, we can use ApplicationContextAware, and get the client by
```
FeignClientInterface client = 
applicationContext.getBean(FeignClientInterface.class);
```



[ Full content available at: https://github.com/apache/dubbo/issues/3990 ]
This message was relayed via gitbox.apache.org for 
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to