Running with springboot 2.2.5 ,which contains spring version: spring-core-5.2.4 and spring-aop-5.2.4.

Scenario: My Listener as below:

@Service
public class UserJoinRoomListener implements ApplicationListener<UserJoinRoomEvent> {
  @Override
  @TraceSource(sampler = RoomEntrySampler.class) //AOP here to trigger #{RoomEntrySampler#process} after current funtion invoked
  public void onApplicationEvent(UserJoinRoomEvent event) {
    System.out.println("Hello ");
  }
}

RoomEntrySampler code as below:

public class RoomEntrySampler{
  @Override
  public void process(UserJoinRoomEvent event) {
    System.out.println("World");
  }
}

when i call ApplicationContext.publishEvent(new UserJoinRoomEvent(xxx,xxx))

Expectation: it should print "Hello World".

Actually: it print "Hello Hello World"

Question: to my understanding, Function "onApplicationEvent"(the proxy object ) should only be invoked at just one time and run at one go. but it's not eventually ,, can i consider this situation as a "Bug"?

Comment From: spencergibb

Are you using spring cloud?

Comment From: freezingWu

yes,I am using the spring cloud version: Hoxton.SR1. when i try to setup a stand alone mini project to reproduce it , it works normal, failed to reproduce.

but when i running the code from my project, it also happened. to check further , i add up a new Listener to catch another events . finally i got some debug screenshot , it make me confuse. the normal screenshot: normal

and bellow is quite different :

problem

to my understanding , when we using the spring multicast , the listener should be proxied with cglib by spring container(as like the normal screenshot), and should only one instance hold by multicaster.

but to the second screenshot, there are two instance (one is proxied with cglib, another is not). so confused. -_-

Comment From: wilkinsona

When Spring Cloud is involved there's a parent application context which can cause events to be received twice as the publishEvent call is propagated to the parent context. Unfortunately, I can't tell if that's what's happening here based on a couple of screenshots, but I think it's the most likely explanation at this stage.

If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.

Comment From: freezingWu

HI, finally, i got the problem reproduced , here is the mini project git: https://gitee.com/ffe/demo-event-bug.git the problem is impacted by Feign .

you can run the test code, and may see the result as bellow: result expected counter is 1, but now got 2 .......

Comment From: wilkinsona

Thanks for the sample. There's quite a bit going on here, but the problem appears to be due to the bean factory attempting to break a circular reference. This results in it having two different views of the DemoListener bean, one where it has been proxied and one where it has not. ApplicationListenerDetector sees the plain DemoListener and then later on, AbstractApplicationEventMulticaster retrieves the demoListener bean and receives the proxied DemoListener. It doesn't consider proxies or their targets at this point so the listener is added twice to allListeners.

We'll transfer this issue to spring-projects/spring-framework so that the Framework team can take a look.

Comment From: freezingWu

so , may i take it as a bug ,and raise it here ?

Comment From: philwebb

@freezingWu No need to re-raise it. We were able to transfer the issue. The Spring Framework team will need to triage it to determine if they consider it a bug or not.

Comment From: snicoll

I did upgrade the sample to a supported version of the framework and got the following running the test:

Enter Aop counter:1
onApplicationEvent counter:1

(with no counter: 2). Sorry this got overlooked but it looks like this was fixed in the meantime. If you can reproduce with a supported version of the framework, please update the sample and we can reopen.