Spring singleton created several times

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

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

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

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

In another class, I'm trying to get an AccessControl instance, something like this:

  ApplicationContext ctx = new ClassPathXmlApplicationContext("acbean.xml"); AccessControl ac = (AccessControl) ctx.getBean("accessControl"); LOGGER_.info("AccessControl Identifier : " + ac.getAccessControlId()); 

I expect the id value to be the same because the id value is set in the constructor, and the constructor should not be called again and again, but this is exactly what happens. Infact, I added a log statement to the constructor, and every new object is created every time.

I 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 that defined twice with two different bean identifiers, and the application context is the same.

Can someone share what is not the way I defined a bean?

I also experimented with singleton = "true" and scope = "singleton", but they are not different.

Thanks.

+6
source share
3 answers

spring's singelton-ness refers to the application context, every time you create a new instance of the application context (for example, the first line in your second code example), all singletones are created.

You need to have one application context and reuse it in your application

+16
source

You create a new application context with each call:

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

This way you get a new spring container, which means your beans are being created again by a new container.

In addition, you mentioned that it was in a web application. If so, you need to allow the web application to load the spring context and receive and use this context as needed.

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. Get the web context through servletcontext as needed.

One more note: one point from spring is to provide inverse control, usually with dependency injection. You should allow spring to introduce any dependencies for you, and not get the context and pull the beans yourself.

+7
source

In a Spring application, you should not explicitly create your own application context.

Ideally, a singleton should be introduced into your class, or you should implement ApplicationContextAware ( docs and some notes ). I prefer an injection; easier.

+2
source

Source: https://habr.com/ru/post/900238/


All Articles