我熟悉Spring。下面奇怪的代码调用构造函数两次,而我期望它被调用一次。有人可以帮忙吗?
package com.tutorialspoint;
import java.util.List;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.ApplicationListener;
public class DemoClass implements ApplicationListener<ContextStartedEvent> {
private String message;
private int nrOfMessages;
public DemoClass(String mes, int nr) {
message = mes;
nrOfMessages = nr;
System.out.println("Demo class constructor. Parameters: " + mes + " " + nr);
}
// a setter method to set List
public void setNrOfMessages(int nr) {
this.nrOfMessages = nr;
}
// Message setter
public void setMessage(String message) {
this.message = message;
}
// prints and returns all the elements of the list.
public void dumpContents() {
System.out.println("Message: " + message + " Nr of messages: " + nrOfMessages);
}
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");
}
}
bean和main:
package com.tutorialspoint;
import java.io.FileNotFoundException;
import java.util.List;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
context.start();
// Create an object
DemoClass obj = (DemoClass) context.getBean("democlassBean");
// Dump contents
obj.dumpContents();
}
}
豆
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="democlassBean" class="com.tutorialspoint.DemoClass"
scope="prototype">
<constructor-arg value="Hello world beans."/>
<constructor-arg value="300"/>
</bean>
<bean class="com.tutorialspoint.InitHelloWorld"></bean>
</beans>
这是输出:
Demo class constructor. Parameters: Hello world beans. 300
BeforeInitialization : democlassBean
AfterInitialization : democlassBean
ContextStartedEvent Received
Demo class constructor. Parameters: Hello world beans. 300
BeforeInitialization : democlassBean
AfterInitialization : democlassBean
Message: Hello world beans. Nr of messages: 300
你可以看到构造函数被称为两次 - 为什么???
这里也是initHelloWorld的代码:
package com.tutorialspoint;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization : " + beanName);
return bean; // you can return any other object as well
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization : " + beanName);
return bean; // you can return any other object as well
}
}
答案 0 :(得分:2)
看来,让原型bean充当ApplicationListener并不是一个好主意。 检查http://forum.spring.io/forum/spring-projects/container/35965-applicationlistener-interface-makes-beans-eagerly-instantiated 详情。
你可以使它工作,但需要一些exta步骤(在有条理的帖子中描述)。请注意,链接的帖子有些陈旧(2007年),其中的某些实现细节很可能不再有效。
如果你真的关心正在创建的实例数 - 那么创建两个类 - 一个作为原型,另一个(singlelton)作为ApplicationListener呢?