简体   繁体   中英

Two objects created in spring why?

I am getting familiar with Spring. Strangely code below invokes constructor twice whereas I expected it to be called once. Can someone help?

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


}

The bean and 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();

    }
}

bean

<?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>

This is the output:

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

You can see constructor is being called twice - why???


Here is also code for 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
   }

}

It seems, it is not good idea to have prototype bean to act as ApplicationListener. Check http://forum.spring.io/forum/spring-projects/container/35965-applicationlistener-interface-makes-beans-eagerly-instantiated for details.

You can make it work, but with some exta steps are required (described in lined post). Note that linked post is somewhat old (year 2007) and it is likely that some of the implementation details covered there are not valid anymore.

If you really care about number of instances being created- what about creating two classes- one as prototype, and another (singlelton) that acts as ApplicationListener?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM