延迟实例=“真”。它做了什么?为什么我不能在不将lazy-init设置为true的情况下从Swing应用程序获取Spring bean?

时间:2011-10-09 17:43:39

标签: java multithreading spring swing java-ee

我有一个应用程序,在后端部署轻量级HTTP服务器(Jetty) servlet基本上更新了MySQL数据库 我用Spring连接了一切。

到目前为止确定。

我有一个用于与服务器交互的UI 如果UI在本地运行,我希望它在JTree当前登录的用户中显示。

所以我决定启动服务器,即在启动主框架时启动Spring。

最重要的是,为了更新UI的JTree以显示我认为使用Observer-Observable的所有已登录用户,并使接受连接的代码为Observable

ConnectionListener会通知ArrayBlockingQueueDefaultMutableTreeNode存储在Jtree中的后台线程(对SwingUtilities根有 public class AdminFrame extends JFrame { public static ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("myBeans"); public static void main(String[] args){ EventQueue.invokeLater(new Runnable() { public void run() { //Show GUI } } } 根>)会更新它 - 当然是通过public class ServerThread extends Thread { @Override public void run() { ClassPathXmlApplicationContext ctx = ApplicationCtx.getApplicationCtx(); } } 在EDT主题中。

我的问题如下:

如果我这样做:

public class ApplicationCtx {  

  private static ClassPathXmlApplicationContext ctx;
  private ApplicationCtx(){}
  public static synchronized ClassPathXmlApplicationContext getApplicationCtx(){  
    if(ctx == null){  
    ctx = new ClassPathXmlApplicationContext("myBeans.xml");  
    }  
    return ctx;  
}  

未绘制GUI但我可以理解,因为一旦Spring启动并且服务器启动,线程就不会返回。

所以我在后端线程中启动Spring,如下所示:

public class AdminFrame extends JFrame {  
    public static void main(String[] args) {  
       ServerThread lightweightServer = new ServerThread();  
       lightweightServer.start();
       Thread.sleep(9000);//Temporary solution to make sure the server is started up before GUI
        ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");
        connectHandler.addObserver(new ConnectionListener());  
        EventQueue.invokeLater(new Runnable() {  
        public void run() {  
              //SHOW GUI
              }  
         }

 ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler");  

}

GUI现在显示并且似乎正常但我错过了通知。

问题:

无法获得新连接的通知:

1)如果我按如下方式注册通知:

AdminFrame

GUI永远不会出现。如果我删除该行:

public class AdminFrame extends JFrame {  
    public static void main(String[] args) {  
       ServerThread lightweightServer = new ServerThread();  
       lightweightServer.start();
       Thread.sleep(9000);//Temporary solution to make sure the server is started up before 
       EventQueue.invokeLater(new Runnable() {
            public void run() {

       AdminFrame frame = new AdminFrame();  
       //Other code

       }

GUI出现。

2)如果我在EDT内部注册,即在 ConnectHandler connectHandler = (ConnectHandler) ApplicationContext.getApplicationCtx().getBean("connectHandler"); 的构造函数内部,GUI也不会显示。

ConnectHandler

如果我删除以下行,GUI会显示,但这样我无法注册以获取通知:

lazy-init="true"

这一定是线程问题,但我无法理解问题是什么 为什么第二次调用Spring应用程序上下文以使{{1}}使线程不返回? 我在这做错了什么?


更新

如果我将Spring配置文件中的属性{{1}}添加到启动Jetty服务器的bean中,问题就解决了。
但我无法理解为什么它会解决它或者问题是什么。

由于

2 个答案:

答案 0 :(得分:1)

  • SerializableObservate需要将GUI相关代码包装到(大多数情况下)invokeAndWait()

  • 来自SwingWorker的输出(因为有保证,但我看到一些不符合我预期效果的情况)或Runnable#Thread需要强奸GUI相关代码到invokeLater()

  • 您可以在之前准备您的GUI(然后存在EDT),并且可见性

JFrame#pack(); 
JFrame#setVisible(true);

对于此Container您必须在invokeXxx();内调用,或者最好来自javax.swing.Action()

答案 1 :(得分:0)

如果将lazy-init设置为true可以解决您的问题,我认为它没有完全解决。

默认情况下,所有bean在启动时初始化,因此如果没有正确初始化任何bean,就会出现启动问题。

如果将其设置为false,则不会调用bean,也不会遇到任何问题。所以这个问题没有解决,而是推迟了。