简体   繁体   中英

Spring singleton created multiple times

I have a bean defined in my spring web application and I am expecting to have only one instance of this bean, here is my bean definition:

<bean id="accessControl" class="my.spring.app.AccessControl" />

In the constructor of AccessControl, I assign an identifier to the object, something like this:

public class AccessControl {
   private long id = 0;
   public AccessControl() {
        id = System.currentTimeMillis();
   }

   public long getAccessControlId() {
        return id;
   }
}

In a different class, I try to get hold of the instance of AccessControl, something like this:

            ApplicationContext ctx =
                     new ClassPathXmlApplicationContext("acbean.xml");

            AccessControl ac = (AccessControl) ctx.getBean("accessControl");
            LOGGER_.info("AccessControl Identifier : " + ac.getAccessControlId());

I am expecting the "id" value to be the same because the value of "id" is set in the constructor and constructor should not get called again and again but that is exactly what is happening. Infact, I added a log statement to the constructor and a new object is created everytime.

I have read: http://www.digizenstudio.com/blog/2006/09/14/a-spring-singleton-is-not-a-singleton/ but I don't think I am dealing with the same class defined twice with two different bean identifiers and the application context is the same.

Can anyone share what is wrong with the way I have defined the bean?

I have also experimented with singleton="true" and scope="singleton" but they do not make any differece.

Thanks.

the singelton-ness in spring is per application context, every time you create a new instance of the application context (like the first line in your second code sample) all the singletons are instantiated.

You need to have a single application context and reuse it around in your application

You are creating a new application context with each call of:

ApplicationContext ctx = new ClassPathXmlApplicationContext("acbean.xml");

So, you end up with a new spring container, which means that your beans are all re-created by the new container.

Also, you mentioned that you had this in a web application. If so, you need to allow the web application to load the spring context and to obtain and use that context as necessary.

Add to web.xml:

<context-param>
    <description>Core Spring context.</description>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<listener>
    <description>Spring loader.</description>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

or something similar. Obtain the web context via a servletcontext as needed.

One other note: one point of spring is to provide inversion of control, commonly with dependency injection. You should consider allowing spring to inject any dependencies for you rather than obtaining the context and pulling beans yourself.

In a Spring app you should not be explicitly creating an application context of your own.

Ideally the singleton should be injected into your class, or you should be implementing ApplicationContextAware ( docs , and some notes ). I prefer injection; easier.

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