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:
and bellow is quite different :
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:
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.