2016-12-13 6 views
0

私は春のアプリケーションがあり、プロトタイプのBeanを固定レートで生成する予定のロジックがあります。これは、最初のスケジュール呼び出しです春の豆の作成フロー:終了時を知る方法?

2016-12-13 04:13:01.885 ERROR 4688 --- [TaskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task. 
... 
BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'metaDataSourceAdvisor': Singleton bean creation not allowed 
while the singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!) 
... 

すべては私のラップトップではなく、私のアプリが原因の起動に失敗したサーバーにデプロイした後、正常に動作します。タイミングの問題のように見えます。私のラップトップアプリケーションでは、はるかに高速に初期化され、最初のスケジュールされた呼び出し(プロトタイプのBeanを生成する)に対して何も間違ったことは起こりません。

Spring Beanの作成フローの現在の状態を知る方法はありますか?スケジュールされたロジックをチェックして、アプリケーションの作成が完了していないときは何も生成できませんか?

ありがとうございます!

+0

完全なコールスタックをポストする必要があります。ラップトップ環境とサーバー環境の違いについてもっと詳しく書くことができますか?サーバーはサーブレット/アプリケーションコンテナであり、開発に使用されたものとは異なりますか? –

+0

こんにちは、クラウス!私の質問です:スケジュールされたロジックでSpringアプリケーションの初期化の現在の状態を教えてくれるSpringコアのすぐに使えるBeanを注入できますか?私はアプリが初期化されていないときにプロトタイプのBeanを生成したくないので、 –

+0

私はSOに関するコメントを持っているので、以下の答えを見てください。基本的にコンテキストの作成はシングルスレッドです。 ApplicationContext.getBean()を呼び出す場合、そのスレッドがスプリングコンテキストのライフサイクルと同期していることを確認してください。スレッドがサーブレットコンテナなどのランタイムによって提供されている場合は、AbstractApplicationContext.isActive()および.isRunning()を使用できますが、すべての並行プログラミングと同様に、状態を読み取った後にコンテキストが閉じられる可能性があります。スプリングで管理されているスレッドに対してのみスプリング操作を実行する必要があります。 –

答えて

1

Springソース(4.3.3と4.2.2)を見ると、これはDefaultSingletonBeanRegistry.getSingleton()の1つの場所でのみ発生し、スプリングコンテキストの初期化に失敗した場合、または明示的に閉じた場合にのみ発生します。 Springは、Beanの作成と起動ライフサイクルメソッドの呼び出しに単一スレッド(呼び出しスレッド)を使用しているため、この原則に違反した場合にのみ例外が発生する可能性があります。

  • スケジュールされたタスクを言うときは、Spring(@Scheduledを使用)によってスケジュールされていることを意味しますか、独自のスケジュールロジックを持っていますか?
  • アプリケーション内のスレッドを起動しますか?その場合、そのスレッドを所有するBeanはSpringのライフサイクルまたはSmartLifecycleインターフェイスを実装していますか?

私はBeanコンストラクタでスレッドを開始する開発者をたくさん見てきましたが、これは非常に悪い考えです。ライフサイクル(スレッド、リソースプール)を持つBeanがある場合は、LifeCycleインターフェイスを常に使用してstart()でリソースを作成し、stop()でクリーンアップする必要があります。これは良いアイデアです。なぜなら、eagerシングルトンがインスタンス化され、コンテキストが完全に配線された後にstart()が呼び出されるため、すべてのBeanを構築できない限りスレッドが作成されないからです。

+0

ありがとう、クラウス! @Scheduled注釈付きメソッドで例外が発生します。このメソッドは、いくつかのプロトタイプBean(Runnableインターフェイスを実装する)を生成し、ExecutorServiceに送信します。私はあなたの助言に従い、LifeCycleインターフェイスを実装しようとします! –

+0

あなたの情報に基づいて、私は春のコンテキストをシャットダウンしている間だけこれを見ることができます:@Scheduledは、すべてのシングルトンが作成されるまで呼び出されるべきではなく、スプリングマネージスレッドによって呼び出されます。あなたのExecutorServiceのライフサイクルはSpringで管理されていないので、beanfactoryを呼び出すことができます。プロトタイプBeanがBeanCreationNotAllowedExceptionで失敗するシングルトンBeanをオートワイヤリングする場合、getBean()は春が終了した後にプロトタイプBeanを取得します。 ExecutorServiceを所有するBeanを作成し、SmartLifeCycleを実装してください。 –

+0

クラウス、迅速な対応と明確な答えをいただきありがとうございます! SmartLifeCycleはまさに私が探していたものです! –