0

我是 spring 新手,我正在尝试弄清楚如何将对象自动连接到控制器。该对象是在运行时从使用 ServletContextListener 启动和停止的任务创建的。我如何告诉 spring 应用程序上下文关于这个对象?

更多细节

我的后台任务从下面的代码开始。我想要alertServer连接到控制器的对象。我可以修改这个类来做到这一点吗?

@WebListener
public class ExecutorContextListener implements ServletContextListener
{
   private static Logger log = Logger.getLogger(ExecutorContextListener.class);

   Thread backgroundThread;
   AlertServer alertServer;

   @Override
   public void contextInitialized(ServletContextEvent event)
   {
      // Start the AlertServer
      alertServer = new AlertServer();

      backgroundThread = new Thread(alertServer, "AlertServer");
      backgroundThread.start();

   }

   @Override
   public void contextDestroyed(ServletContextEvent event)
   {
      alertServer.stop();
      try
      {
         backgroundThread.join();
      }
      catch (InterruptedException e)
      {
         log.error("contextDestroyed Exception", e);
      }
   }
}

更新

提供的评论和答案对找到解决方案非常有帮助。通过 Sotirios Delimanolis 和 Dave Newton 提供的信息,我意识到现在我正在 Spring 之上构建我的解决方案,我实际上并不需要首先使用 ServletContextListener。我真正想做的就是启动一个可用于 Spring 控制器的后台线程,所以我将这段代码放在我的 servlet-context.xml 中,然后我就可以运行了。

<beans:bean id="alertServer" class="com.springmvcproj.AlertServer">
    <beans:property name="serverPort" value="56543" />
</beans:bean>

<beans:bean id="AlertServerThread" class="java.lang.Thread" init-method="start">
  <beans:constructor-arg ref="alertServer"/>
</beans:bean>
4

1 回答 1

1

正如 Dave Newton 在评论中所说,Spring 只能将它管理的 bean 注入它管理的其他 bean。带有注释@WebListener的类是由 servlet 容器管理的类,因此永远不会出现在您的 Spring 上下文中。即使是这样(因为您创建了一个bean条目),它也不会是 servlet 容器使用的那个。

解决此问题的一种方法是使用 SpringWebApplicationInitializer代替(或同时)使用web.xml描述符。此接口提供了一种onStartup(ServletContext)方法,您可以在其中注册 Servlet、过滤器和侦听器,就像在 aweb.xml或 with中一样@WebXXX。就像是

public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
    final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(YourApplicationContext.class); // or some xml file
    rootContext.refresh();

    // Manage the life-cycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));

    // Create the dispatcher servlet's context
    final AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(DispatcherContext.class);

    final ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
    dispatcher.setAsyncSupported(true);
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");

    container.addListener(dispatcherContext.getBean(ExecutorContextListener.class)));

    ...// more registrations
}

因此,上面假设您AnnotationConfigWebApplicationContext dispatcherContext包含一个 bean 类型ExecutorContextListener。因为 Spring 正在管理这个 bean,所以您可以在 this和class中添加@Autowired@Inject注入相同的AlertServer实例。在这种情况下,您不会在方法中对其进行初始化。ServletContextListener@ControllercontextInitialized()

第二种选择是

  1. AlertServer对象作为属性添加到ServletContext.
  2. 注入ServletContext你的@Controller班级。
  3. 从属性中检索AlertServer对象。ServletContext

以上是可能的,因为该contextInitialized()方法总是在您的任何控制器开始处理请求之前运行。

于 2013-09-05T20:56:19.903 回答