2016-08-03 4 views
3

にアプリケーションコンテキストをロードした後にコードを実行します。私は春のブートコマンドラインアプリケーション(つまり、ローカルウェブサーバ)は春のブートコマンドラインアプリケーション

@SpringBootApplication 
public class MyApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(LocatesRecApplication.class, args); 
    } 

} 

別々のコンポーネントがCommandLineRunnerを実装して、プログラムの引数を解析し、ログPERSから

@Component 
public class ApplicationRunner implements CommandLineRunner { 

    @Autowired 
    private MyService someService; 

    @Override 
    public void run(String... strings) throws Exception {   
    someService.run(); 
    } 

} 

問題1

:とサービスを実行前述のアプリケーションが実装コンポーネントの注入されたコンポーネントに含まれるようにアプリケーションロジックの実行を終了すると、最後の2つのメッセージは、アプリケーションコンテキストが開始されたことを示してすぐに終了します。アプリケーションが期待実行として一方で、上記の行は、直感的ではありません。

2016-08-03 14:24:41.254 INFO 9176 --- [main] com.xx.yyy.MyApplication: Started MyApplication in 25.885 seconds (JVM running for 26.962) 
2016-08-03 14:24:41.254 INFO 9176 --- [main] s.c.a.AnnotationConfigApplicationContext : Closing org.spring[email protected]7193666c: startup date [Wed Aug 03 14:24:16 BST 2016]; root of context hierarchy 

同様に、コンポーネントの実行のいずれかの中にキャッチされない実行時例外がある場合は、スタックトレースが行で始まります:

java.lang.IllegalStateException: Failed to load ApplicationContext 

アプリケーションロジックを実行する前に直感的にアプリケーションコンテキストが読み込まれるため、これもまた非常に混乱します。

通報2

上記使用のコードパターンは新しい@Jsontestアノテーションを使用してユニットテストで混乱を引き起こします。このため

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.xx.yyy.MyApplication$ApplicationRunner': Unsatisfied dependency expressed through constructor parameter 1: No qualifying bean of type [com.xx.yyy.service.MyService] found for dependency [com.xx.yyy.service.MyService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. 

現在の回避策はで私のCommandLineRunner実装を維持することである。このようなテストの実行がコンポーネントのスキャンを有効にしないようautowired依存関係(上記SomeServiceが、)負荷に失敗しているため、アプリケーション・コンテキストがロードに失敗しました@SpringBootApplicationクラスとは別のクラスなので、後者は上記のスニペット以上は行いません。

質問

上記の問題を解決することができる場合、私は疑問に思います。おそらく、アプリケーションのコンテキストがロードされた後にアプリケーションを実行できるようにする別のパターンを使用していますか?

答えて

0

2点の一つは明らかに起こっている:SomeServiceはあなたApplicationRunnerのコンテキストで初期化されていない、またはApplicationRunnerSomeService前に初期化されているいずれか。私は、2つが同じ文脈構成の一部であることを確認したいと思います。それは問題ではない場合、あなたはそれがCommandLineRunnerよりも高いロードの優先順位を取得することを保証するために、サービスのBean宣言に@Order注釈を追加することができます。

@Order(1) 
@Service 
public class MyService { ... } 

@Component 
public class ApplicationRunner implements CommandLineRunner { ... } 
1

CommandLineRunnerインタフェースは、「初期化」を処理するために、より多くのように見えますタイプのもの。ご存じのように、Spring Bootフレームワークは起動時にそれらを実行し、起動が完了するまで起動の完了を考慮しません。

あなたのコマンドラインアプリケーションを実行するためのちょうど1「メイン」タスクがある場合、私は、アプリケーションのmainメソッドの一部としてそれを実行することをお勧めしたい:

try (final ConfigurableApplicationContext applicationContext = SpringApplication.run(MyApplication.class, args)) { 
     applicationContext.getBean(MyClassThatDoesStuff.class).run(); 
    } 

アプリケーションは、コマンドライン引数を使用している場合は、適切なBeanプロパティの設定などを処理するCommandLineRunnerを持つこともできます。

このアプローチでは、Springコンテキストが完全に開始されているので、コンテキストで何をしたいかを選択して閉じて終了します。

関連する問題