Spring在服务器启动时自动启动一个类

时间:2017-08-15 09:31:56

标签: java spring

我有一个弹簧应用程序。我正在自动上课,他们工作正常。 例如

@Controller
public class SearchController {
    @Autowired
    private EnvironmentControl envControl;
    @Autowired
    private SearchControl searchControl;
...

但是现在我有一个名为ScheduleServlet的服务器启动类,它使用init方法来安排某些事情......

public class SchedulerServlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {

    super.init(config);
    this.LOGGER.info("timer servlet is initialized  ");
    try {
        InitialContext ic = new InitialContext();
        TimerManager tm = (TimerManager) ic.lookup("java:comp/env/tm/TimerManager");
        Timer timer = tm.schedule(new GlobalTemplateScheduler(), 0, 3600000);// one hour interval
        System.out.println("Timer..... " + timer);
    }
...

在我的GlobalTemplateScheduler类中有timerExpired方法,该方法计划在每隔一小时间隔后执行。

public class GlobalTemplateScheduler implements TimerListener {

    @Autowired
    private TemplateControl templateControl;

    @Override
    public void timerExpired(Timer timer) {
        try {
            templateControl.updateMappings(names);
        } catch (Exception e) {
            this.LOGGER.error(e.getMessage());
            e.printStackTrace();
        }
...

所以我必须自动装配templateControl,我得到null。这应该在服务器启动时发生。

进一步在updateMappings里面有一个数据源对象,它也被自动装配为constructor-arg(这在浏览器请求上工作正常但需要在服务器启动时执行)。

注意:我无法使用ApplicationListener接口。

任何建议都会有所帮助。

三江源。

3 个答案:

答案 0 :(得分:0)

在应用程序启动时,bean初始化将无法完成,bean可以在应用程序上下文刷新之后或在bean初始化之后使用,在启动时执行需要bean的逻辑是没有意义的,除非您检测是否豆子准备好了。

你可以在bean中使用@PostConstruct执行一些逻辑,这将在bean初始化之后执行,这样你就可以在bean初始化之后以一种方式操作你的逻辑,或者你可以在之后检测并执行逻辑ContextRefreshedEvent通过命令applicationListener并将你的逻辑放在onAppplicationEvent方法中。

答案 1 :(得分:0)

一种解决方案是在servlet中使用Spring的Container。为此目的有许多implementations,例如AnnotationConfigApplicationContext。 Spring的文档描述了如何使用ClassPathXmlApplicationContext

假设GlobalTemplateScheduler也是一个bean,那么关键点是:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

GlobalTemplateScheduler sheduler = context.getBean("sheduler", GlobalTemplateScheduler.class);

sheduler.someMethod();

ClassPathXmlApplicationContext使用的XML内容很小。但是您需要启用组件扫描:

<context:component-scan base-package="foo.bar.baz" />

我可以建议另一种方法是使用Spring的DispatcherServlet将所有bean连接在一起。它可以使用相同的XML,只需加载它即可。好处是您不需要自己加载应用程序上下文并启动bean作为入口点

有很多教程如何使用这个servlet。

如果您不想编写XML,可以使用WebApplicationInitializer

答案 2 :(得分:0)

正如我所说,我自动装配的咖啡豆工作正常。我只需要调度程序Servlet中的那些bean。

这是有效的解决方案......

在我的调度程序servlet中,我获得了应用程序上下文xml并使用了所需的bean ...

ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
GlobalTemplateControl globalTemplateControlObject = context.getBean("globalTemplateControl", GlobalTemplateControl.class);

感谢@duffymo @Amer Qarabsa @Spindizzy的建议:)