春天有点新鲜.当我通过接口实例化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类,并且还更改HelloWorld为HelloWorldImplmain内部(两次出现 - 基本上在我调用的行上getBean),那么这也适用于原型bean.那为什么会这样?另外,如果我HelloWorldImpl以main段中描述的方式创建main的两个实例,那么事件仍然只被接收一次(但这可能是单独的问题).
当使用基于 java 的配置时,发生的事情是在进程的早期阶段@Configuration使用 ASM 读取类(它们还没有通过类加载器加载)。基于读取的字节码,Spring 创建 bean 定义和基于代理的类。
方法@Bean(无论它在哪里)基本上与 相同FactoryBean。它或多或少以相同的方式起作用。创建元数据时,它通过检查方法签名并使用返回类型创建工厂来实现。该返回类型基本上用于getObjectTypea 的方法FactoryBean。该方法的结果用于确定 bean 支持什么。
HelloWorld现在,当作为类型返回时,您将获得一个创建该类型 bean 的工厂。使用时,HelloWorldImpl您将获得一个创建该类型 bean 的工厂。第一个不包含ApplicationListener接口,因此被 spring 忽略,但第二个包含(在生成(自动)配置元数据时检测到)。
因此,在使用@Configurationwith时@Bean,尽可能具体地说明返回类型非常重要。
| 归档时间: |
|
| 查看次数: |
547 次 |
| 最近记录: |