春天创造的两个对象为什么?

时间:2016-05-27 17:51:46

标签: java spring

我熟悉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
   }

}

1 个答案:

答案 0 :(得分:2)

看来,让原型bean充当ApplicationListener并不是一个好主意。 检查http://forum.spring.io/forum/spring-projects/container/35965-applicationlistener-interface-makes-beans-eagerly-instantiated 详情。

你可以使它工作,但需要一些exta步骤(在有条理的帖子中描述)。请注意,链接的帖子有些陈旧(2007年),其中的某些实现细节很可能不再有效。

如果你真的关心正在创建的实例数 - 那么创建两个类 - 一个作为原型,另一个(singlelton)作为ApplicationListener呢?