我正在尝试使用Weld-SE引导一个小型javafx应用程序。如果我删除Menubar上的@Inject注释并手动实例化它,我就能够运行应用程序。但是当我添加@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发布于 2013-02-14 05:02:04
ShaggyInjun,您指的是Initializable接口,它表明您正在尝试与FXMLLoader集成。下面的所有信息都假设您正在使用FXML进行接口定义,并且只讨论了有关将值注入到FXML控制器中的问题。
FXMLLoader具有控制器工厂的概念,您应该使用它将控制器实例化与依赖注入系统集成在一起。在甲骨文的Mastering FXML Tutorial中有一个关于控制器工厂的简要讨论。Andy演示了definition of such a factory for Guice in his blog,并且有一个comprehensive integration of Guice in FXML on github。
对于Weld,您将需要实现类似的控制器工厂回调机制,以实现Weld提供的依赖注入功能。您在评论FXML & JavaFX—Fueled by CDI & JBoss Weld中链接的Matthieu Brouillard的文章似乎提供了将焊接和接口焊接初始化到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创建了控制器,情况就不是这样了。
还有另一种选择,那就是使用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-02 09:01:30
是因为您试图在构造函数或初始化块中使用menuBar吗?
如果是这样,请尝试使用Initializable并在initialize中使用它们。
发布于 2013-02-14 04:13:06
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中初始化变量似乎确实有效。
根据可初始化文档,initialize is Called to initialize a controller after its root element has been completely processed. Initializable
初始化和@PostConstruct调用的顺序
我认为可以放心地理解initialize的调用与对象构造没有任何关系。相反,initialize是在当前节点图的根被完全处理后调用的,因此可以处理事件处理程序等document.onload或jQuery(document).ready()代码行中的内容。如果在对象图准备就绪之前尝试附加事件处理程序,则很有可能看到空指针,因为节点不是对象图,因此无法附加事件处理程序。
因此,在将对象加载到场景图之前,您需要实例化对象(直接或通过注入)。因此,@PostConstruct在初始化之前被调用。但是,如果您直接实例化对象,则调用注释为@PostConstruct的方法的责任落在您身上,否则后期处理将不会发生。
结论:可以安全地假设initialize总是在带有@PostConstruct注释的方法之后调用。
编辑
@珠海指出了一些我没有在上面列出的假设。所以就是这样,上面的情况对我来说是有效的。
使用FXML文件作为在views.
https://stackoverflow.com/questions/14654627
复制相似问题