0

Weld-SEを使用して小さなjavafxアプリケーションをブートストラップしようとしています。@Injectのアノテーションを削除しMenubarて手動でインスタンス化すると、アプリケーションを実行できました。しかし、@ Injectを追加すると、アプリケーションは例外をスローします。以下にリストされているのは、注入ポイントとプロデューサーメソッドです。これが私が行ったすべての構成ですが、何かが足りませんか?

インジェクションポイント

@Inject MenuBar menuBar

プロデューサーメソッドを使用したクラス

public class ComponentProducer {

    @Produces
    public MenuBar createMenuBar(){
        return new MenuBar();
    }

}

例外

    491 [JavaFX Application Thread] INFO org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available.    Transactional observers will be invoked synchronously.
    8868 [JavaFX Application Thread] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
    8868 [JavaFX Application Thread] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
    Exception in Application start method
    Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:399)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:722)

    Caused by: java.lang.NullPointerException
at net.sourceforge.squirrel_sql.client.MainScene.<init>(MainScene.java:26)
at net.sourceforge.squirrel_sql.client.FXApplication.startup(FXApplication.java:176)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:304)
at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54)
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163)
at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:298)
at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:200)
at org.jboss.weld.introspector.ForwardingWeldMethod.invokeOnInstance(ForwardingWeldMethod.java:59)
at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstanceWithSpecialValue(MethodInjectionPoint.java:194)
at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:241)
at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:216)
at org.jboss.weld.manager.BeanManagerImpl.notifyObservers(BeanManagerImpl.java:654)
at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:647)
at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:641)
at org.jboss.weld.event.EventImpl.fire(EventImpl.java:93)
at net.sourceforge.squirrel_sql.client.Main.start(Main.java:180)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:315)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:174)
at com.sun.javafx.application.PlatformImpl$3.run(PlatformImpl.java:141)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication$2$1.run(GtkApplication.java:79)
... 1 more
4

3 に答える 3

1

コンストラクターまたは初期化ブロックで menuBar を使用しようとしているからですか?

その場合は、Initializable を使用して、初期化で使用してみてください。

于 2013-02-02T01:01:30.367 に答える
1

ShaggyInjun さん、 FXMLLoaderと統合しようとしていたことを示すInitializableインターフェースを参照しています。以下のすべての情報は、インターフェイス定義に FXML を使用していることを前提としており、FXML コントローラーへの値の注入に関する問題のみを説明しています。

FXMLLoaderには、コントローラー ファクトリの概念があり、コントローラーのインスタンス化を依存性注入システムと統合するために使用する必要があります。コントローラ ファクトリについては、Oracle のMastering FXML Tutorialで簡単に説明しています。Andyは彼のブログで Guice のそのようなファクトリの定義を示しており、github には FXML での Guiceの包括的な統合があります。


Weld では、Weld が提供する依存性注入機能を実現するために、同様のコントローラー ファクトリ コールバック メカニズムを実装する必要があります。コメントでリンクした Matthieu Brouillard の記事FXML & JavaFX—Fueled by CDI & JBoss Weldは、Weld の初期化と Weld の FXMLLoader コントローラー ファクトリ メカニズムへのインターフェイスの両方に必要なすべての情報を提供しているようです。具体的には、次のコードは、Andy Till の FXML ベースのインジェクション メカニズムに相当する Weld です。

public class FXMLLoaderProducer {
  @Inject Instance<Object> instance;
  @Produces public FXMLLoader createLoader() {
    FXMLLoader loader = new FXMLLoader();
    loader.setControllerFactory(new Callback<Class<?>, Object>() {
      @Override public Object call(Class<?> param) {
        return instance.select(param).get();
      }
    });
    return loader;
  }
}

FXMLoader コントローラ ファクトリが使用されている場合でも、コントローラをインスタンス化しているのは FXMLLoader だと思います。そのような場合、依存性注入システムがオブジェクトのライフサイクルを維持している場合にのみ適用されるため、ようなアノテーションを作成しないでください@PostConstruct。これは、FXMLLoader がコントローラーを作成する場合には当てはまりません。

別の方法が 1 つあります。それは、 setController を使用してFXMLLoaderで使用されるコントローラーを明示的に設定することです。これにより、依存性注入システムが任意の手段を使用してコントローラーをインスタンス化 (および注入) できるようになり、その後、インスタンス化されたコントローラーを FXMLLoader に渡すことができます。このような場合@PostConstruct、依存性注入システムがオブジェクトのライフサイクルを維持しているため、 のようなアノテーションが機能するはずです (また@PostConstruct、コントローラーが作成された後、コントローラーを FXMLLoader に渡す前に、依存性注入システムによって呼び出されます)。


Andy の Guice ベースのソリューションをここに投稿します。これは、Guice で同様のインジェクションを行う方法の小さくて単純な例です (彼のブログがオフラインになった場合に備えて)。

class GuiceControllerFactory implements Callback<Class<?>, Object> {
  private final Injector injector;
  public GuiceControllerFactory(Injector anInjector) {
    injector = anInjector;
  }     
  @Override public Object call(Class<?> aClass) {
    return injector.getInstance(aClass);
  }
}
于 2013-02-13T21:02:04.077 に答える
0

EJBのドキュメントには、@ PostConstructで注釈が付けられたメソッドは、インジェクションが実行された後に呼び出され、これが可変インジェクションを期待するメソッドであると記載されています。

@PostConstruct

The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.

ただし、変数が内部で初期化されることを期待することはinitialize機能しているようです。

Initializableのドキュメントによると、initializeはCalled to initialize a controller after its root element has been completely processed. Initializableです。

初期化と@PostConstructの呼び出しの順序

initializeの呼び出しは、オブジェクトの構築とは何の関係もないことを理解するのは安全だと思います。代わりに、現在のノードグラフのルートが完全に処理されたときにinitializeが呼び出されるため、イベントハンドラーなどを処理できます。document.onloadまたはの行にあるものjQuery(document).ready()。オブジェクトグラフの準備が整う前にイベントハンドラーをアタッチしようとすると、ノードがオブジェクトグラフではないため、イベントハンドラーをアタッチできなくなるため、nullポインターが表示される可能性がかなり高くなります。

したがって、オブジェクトをシーングラフにロードする前に、オブジェクトを(直接または注入を介して)インスタンス化します。したがって、@PostConstructは初期化の前に呼び出されます。ただし、オブジェクトを直接インスタンス化する場合は、@ PostConstructという注釈の付いたメソッドを呼び出す責任があります。そうしないと、後処理は行われません。

結論:@PostConstructで注釈が付けられたメソッドの後に、initializeが常に呼び出されると想定しても安全です。

編集

@Jewelseaは、私が上にリストしていないいくつかの仮定を指摘しました。だからここに行く、上記が私のために働いた状況。

  • ビューにFXMLファイルを使用する。
  • fxmlファイル内で指定されたコントローラー名。
于 2013-02-13T20:13:06.117 に答える