通过接口使用时在原型bean上发出接收事件?

gio*_*gim 7 java spring

春天有点新鲜.当我通过接口实例化bean时,它似乎不会获取事件,但是,如果我使用实际的类实现接口,则接收事件.为什么是这样?代码如下.

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;
    }

    @Override
    public void printHelloWorld() {

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


    public void onApplicationEvent(ContextStartedEvent event) {
          System.out.println("ContextStartedEvent Received");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是调用代码:

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

     // Let us raise a start event.
    ctx.start();           

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

    ctx.stop();
}
Run Code Online (Sandbox Code Playgroud)

配置类:

@Configuration
public class HelloWorldConfig {

   @Bean 
   @Scope("prototype")
   public HelloWorld helloWorld(){
      return new HelloWorldImpl("Hello java beans");
   }



}
Run Code Online (Sandbox Code Playgroud)

界面:

package javabeans.di;

public interface HelloWorld {

    void printHelloWorld();

}
Run Code Online (Sandbox Code Playgroud)

如果bean具有原型范围,则"ContextStartedEvent Received"永远不会显示.

注意:如果我将bean方法的返回类型更改HelloWorldImpl为config类,并且还更改HelloWorldHelloWorldImplmain内部(两次出现 - 基本上在我调用的行上getBean),那么也适用于原型bean.那为什么会这样?另外,如果我HelloWorldImpl以main段中描述的方式创建main的两个实例,那么事件仍然只被接收一次(但这可能是单独的问题).

M. *_*num 3

当使用基于 java 的配置时,发生的事情是在进程的早期阶段@Configuration使用 ASM 读取类(它们还没有通过类加载器加载)。基于读取的字节码,Spring 创建 bean 定义和基于代理的类。

方法@Bean(无论它在哪里)基本上与 相同FactoryBean。它或多或少以相同的方式起作用。创建元数据时,它通过检查方法签名并使用返回类型创建工厂来实现。该返回类型基本上用于getObjectTypea 的方法FactoryBean。该方法的结果用于确定 bean 支持什么。

HelloWorld现在,当作为类型返回时,您将获得一个创建该类型 bean 的工厂。使用时,HelloWorldImpl您将获得一个创建该类型 bean 的工厂。第一个不包含ApplicationListener接口,因此被 spring 忽略,但第二个包含(在生成(自动)配置元数据时检测到)。

因此,在使用@Configurationwith时@Bean,尽可能具体地说明返回类型非常重要。