Giorgi Moniava Giorgi Moniava - 4 months ago 8x
Java Question

Issue receiving event on prototype bean when used through interface?

A little bit new with spring. When I instantiate a bean via interface, it doesn't seem to get events, if however, I use actual class implementing the interface, then the event is received. Why is this? Code below.

package javabeans.di;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;

public class HelloWorldImpl implements HelloWorld, ApplicationListener<ContextStartedEvent> {

private String msg;

public HelloWorldImpl(String s){
msg = s;

public void printHelloWorld() {

System.out.println("Hello : " + msg);

public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");

Here is the calling code:

public static void main(String[] args) {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfig.class);

// Let us raise a start event.

HelloWorld obj = (HelloWorld) ctx.getBean("helloWorld");


Config class:

public class HelloWorldConfig {

public HelloWorld helloWorld(){
return new HelloWorldImpl("Hello java beans");


The interface:

package javabeans.di;

public interface HelloWorld {

void printHelloWorld();


"ContextStartedEvent Received" never gets shown if the bean has a prototype scope.

NOTE: If I change return type of bean method to
in the config class, and also change
inside main (two occurrences - basically on the line where I call
), then this works also with prototype beans.
Why would that be? Additionally if I create two instances of
in main, in a manner described in this paragraph, still the event is received only once (but that might be separate issue).


When using java based configuration what happens is very early in the process the @Configuration classes are read with ASM (they aren't loaded through a class loader yet). Based on that read bytecode Spring creates the bean definitions and proxy based classes.

A @Bean method (regardless where it is) is basically the same as a FactoryBean. It acts more or less in the same way. When the meta data is created it does so by inspecting the method signature and using the return type to create a factory. This return type is basically used for the getObjectType method of a FactoryBean. And this the result of that method is used to determine what the bean supports.

Now when return HelloWorld as a type you get a factory creating beans of that type. When using HelloWorldImpl you will get a factory creating beans of that type. The first doesn't contain the ApplicationListener interface and as such is ignored by spring, the second however does (it is detected at that point of generating the (auto) configuration meta data).

So when using @Configuration with @Bean it is important to be as specific as possible about the return type.