2012-02-02 6 views
2

Использование Spring 3.0.x, я столкнулся с проблемой, когда запущен Bean init-method, и как часть его извлекает некоторую информацию, а затем в другой поток (исходный поток init() ожидает других потоков для complete) пытается получить один или несколько Beans на основе этой информации. Проблема в том, что эти другие Бобы являются одноэлементными и еще не инициализированы. В методах getSingleton() есть синхронизированный() блок в DefaultSingletonBeanRegistry.Как запустить метод после завершения инициализации синглэна Spring?

Проблема заключается в том, что я пытаюсь получить/инициализировать Bean, пока я в настоящее время инициализирую Bean, поэтому я застрял в основном потоке в методе init(), а другой поток пытается получить еще один синглтон Bean, и заблокирован, потому что у 1-го потока есть блокировка.

Итак, как я понимаю, у меня есть 2 варианта:

1) Получить Spring запустить метод ПОСЛЕ одноточечно был полностью создан, который выполняет выборку фактических данных и обработки 2) Придумайте сообщение, которое передает данные обратно в основной поток, а затем обрабатывать их все внутри него, поскольку он уже имеет блокировку монитора.

Мысли? Идеи? Как я получу # 1?

+0

Являются ли одиночные игры ленивыми или нет?Вы знакомы с этими зависимостями раньше, или они получены в методе init на основе некоторых вычислений? –

+0

Нет, они не настроены на ленивую загрузку, и я не знаю, какие зависимости находятся во время компиляции, потому что они исходят из вызова API, который выполняется во время вызова init(). – Drizzt321

ответ

5

Вы пробовали реализовать интерфейс InitializingBean

class MyBean implements InitializingBean{ 

    @Override 
    public void afterPropertiesSet(){ 
     // fetch information, etc 
    } 
} 

Согласно документации:

Интерфейс быть реализован бобами, которые должны сразу реагировать все их свойства были> установить с помощью BeanFactory : например, для выполнения пользовательской инициализации ...

+0

Я видел это, но вызывает ли это вызов до или после того, как Spring завершила инициализацию Bean и вышла из класса DefaultSingletonBeanRegistry и выпустила блокировку, вызывающую проблему? Возможно, мой google-fu терпит неудачу, но мне не удалось найти действительно хорошую диаграмму, показывающую фазы и место их проведения для инициализации Bean. – Drizzt321

+0

Что вы определяете как «инициализацию боба»? Это называется после того, как все свойства bean были установлены (все поля \ @Autowired и \ @Value). Поэтому да, это нужно вызывать после того, как bean был инициализирован, однако я не знаю точных данных о том, вышел ли он из класса DefaultSingletonBeanRegistry. Это поможет, если вы разместите свой код инициализации, который вызывает проблемы. Но я бы посоветовал вам сначала попробовать этот ответ. – ggreiner

2

Вы можете реализовать Lifecycle интерфейс. Обратные вызовы жизненного цикла происходят, когда start()/stop() вызывается в охватывающем подклассе AbstractApplicationContext, который происходит после инициализации всех одноэлементных bean-компонентов (вызванных зависимостями и вызванных методов init). Обратные вызовы жизненного цикла также следуют за порядком зависимостей, как это делает инициализация.

1

Вы не указали, какую конфигурацию вы используете (на основе аннотации или на основе XML), но в конфигурации XML-компонента вы можете использовать атрибут depends-on, чтобы убедиться, что последовательность компонентов, которые вам нужны, была выполнена в надлежащий порядок.

Например, если у вас есть два бобы:

<bean id="bean1" class="my.package.class" /> 
<bean id="bean2" class="my.package.class2" /> 
<bean id="bean3" class="my.package.class3" depends-on"bean1, bean2" /> 

В этом случае, bean1 и bean2 будут создаваться в неподтвержденной порядке. Spring пытается создать экземпляр на основе порядка XML-файла, но для этого нет никакой гарантии. Тем не менее bean3 гарантированно не создается при создании экземпляра bean1 и bean2.

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

В худшем случае вы всегда можете создать экземпляр всех компонентов, и после создания экземпляра вы можете использовать FactoryMethodInvokingBean для вызова статического метода после создания компонента. Еще раз убедитесь, что вы используете depends-on, чтобы гарантировать, что FactoryMethodInvokingBean вызывается после создания экземпляра компонента singleton.

+0

Использование XML основано, но я не знаю всех имен bean-объектов, к которым я буду обращаться, поскольку имена определяются вызовом API другой системе, поэтому я не могу легко установить это заранее. – Drizzt321

+0

Вы пытались установить lazy-init = "false" на ваши компоненты, чтобы убедиться, что они инициализируются при запуске? –

Смежные вопросы