Spring Singleton создан несколько раз - PullRequest
6 голосов
/ 27 октября 2011

В моем весеннем веб-приложении определен bean-компонент, и я ожидаю, что у меня будет только один экземпляр этого bean-компонента. Вот мое определение bean-компонента:

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

В конструкторе AccessControl я назначаюидентификатор объекта, примерно так:

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

   public long getAccessControlId() {
        return id;
   }
}

В другом классе я пытаюсь получить экземпляр AccessControl, что-то вроде этого:

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

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

Я ожидаюзначение «id» должно быть одинаковым, потому что значение «id» устанавливается в конструкторе, и конструктор не должен вызываться снова и снова, но это именно то, что происходит.Фактически, я добавил оператор log в конструктор, и каждый раз создается новый объект.

Я прочитал: http://www.digizenstudio.com/blog/2006/09/14/a-spring-singleton-is-not-a-singleton/, но я не думаю, что имею дело с одним и тем же классом, определенным дважды сдва разных идентификатора компонента и один и тот же контекст приложения.

Кто-нибудь может поделиться тем, что не так с тем, как я определил компонент?

Я также экспериментировал с singleton = "true" иscope = "singleton", но они не делают различий.

Спасибо.

Ответы [ 3 ]

17 голосов
/ 28 октября 2011

значение singelton-ness весной зависит от контекста приложения, каждый раз, когда вы создаете новый экземпляр контекста приложения (например, в первой строке второго примера кода), создаются все синглеты.

Вам необходимо иметь один контекст приложения и повторно использовать его в своем приложении

7 голосов
/ 28 октября 2011

Вы создаете новый контекст приложения с каждым вызовом:

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

Итак, у вас получился новый пружинный контейнер, а это значит, что все ваши бобы воссоздаются новым контейнером.

Кроме того, вы упомянули, что это было в веб-приложении. Если это так, вам нужно разрешить веб-приложению загружать контекст Spring и получать и использовать этот контекст по мере необходимости.

Добавить в 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>

или что-то подобное. При необходимости получите веб-контекст через сервлет-текст.

Еще одно замечание: одной из точек пружины является обеспечение инверсии управления, обычно с инжекцией зависимостей. Вам следует подумать о том, чтобы разрешить Spring вводить любые зависимости для вас, а не получать контекст и извлекать компоненты самостоятельно.

2 голосов
/ 28 октября 2011

В приложении Spring вы не должны явно создавать собственный контекст приложения.

В идеале синглтон должен быть внедрен в ваш класс, или вы должны реализовывать ApplicationContextAware ( документы и некоторые заметки ).Я предпочитаю инъекции;проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...