У меня есть график Spring beans, который автоматически связывает друг с другом. Тяжелая упрощенная иллюстрация:
<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>
...
public class Foo {
@Autowired Bar bar;
@Autowired Baz baz;
}
public class Bar {
@Autowired Foo foo;
}
public class Baz {
@Autowired Foo foo;
}
Все эти beans не имеют определенной области, которая подразумевает, что они являются одиночными (что делает их явные синглтоны ничего не меняет, я пробовал).
Проблема заключается в том, что после создания одного контекста приложения экземпляры Bar
и Baz
содержат разные экземпляры Foo
. Как это могло случиться?
Я попытался создать public no args constructor для Foo
, и отладка подтвердила, что Foo
создается несколько раз. Трассировка стека для всех этих созданий здесь.
Я также попытался включить ведение журнала отладки для Spring и среди всех других строк получил следующее:
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
Я понимаю, что мои beans перекрестно ссылаются друг на друга, но я ожидал бы, что структура Spring будет уважать одноэлементную область и инициализировать singleton bean один раз, а затем автоматически отнести ее к тому, кто ее хочет.
Интересный факт: если я использую конструктор старой школы private
с public static Foo getInstance
accessor, это работает просто отлично - во время настройки контекста не выбрасываются исключения.
FWIW, я использую Spring версию 3.0.5 (также пробовал с 3.1.2, те же результаты) с конструктором o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
.
Я могу легко преобразовать свой код, чтобы использовать статический инициализатор, но я хочу понять, почему Spring ведет себя так. Это ошибка?
EDIT:. Некоторые дополнительные исследования показали, что
- После инициализации контекста приложения все последующие запросы
context.getBean(Foo.class)
всегда возвращают один и тот же экземплярFoo
. - Замена
@Autowired
на сеттеры (около 20 применений этого bean) все еще приводит к нескольким конструкциям этого объекта, но все зависимости вводятся с помощью той же ссылки.
Как мне кажется выше, это ошибка Spring, относящаяся к реализации @Autowired
. Я собираюсь публиковать сообщения на форумах сообщества Spring и возвращаться сюда, если мне удастся получить что-нибудь полезное.