在Spring中启动时执行方法

时间:2010-03-08 13:16:29

标签: java spring

第一次启动应用程序时,是否有任何Spring 3功能可以执行某些方法?我知道我可以设置一个带@Scheduled注释的方法,然后在启动后执行,但它会定期执行。

13 个答案:

答案 0 :(得分:175)

如果“应用程序启动”是指“应用程序上下文启动”,那么是的,有many ways to do this,最简单的(对于单例bean,无论如何)要用@PostConstruct注释您的方法。看一下链接以查看其他选项,但总的来说它们是:

  • 使用@PostConstruct
  • 注释的方法 {li> afterPropertiesSet()InitializingBean回调接口定义
  • 自定义配置的init()方法

从技术上讲,它们是 bean 生命周期的钩子,而不是上下文生命周期,但在99%的情况下,这两者是等价的。

如果您需要专门挂钩上下文启动/关闭,那么您可以改为implement the Lifecycle interface,但这可能是不必要的。

答案 1 :(得分:96)

使用ApplicationListener可轻松完成此操作。我听到了Spring ContextRefreshedEvent

的工作
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class StartupHousekeeper implements ApplicationListener<ContextRefreshedEvent> {

  @Override
  public void onApplicationEvent(final ContextRefreshedEvent event) {
    // do whatever you need here 
  }
}

应用程序侦听器在Spring中同步运行。如果你想确保你的代码只执行一次,只需在你的组件中保留一些状态。

<强>更新

从Spring 4.2+开始,您还可以使用@EventListener注释来观察ContextRefreshedEvent(感谢@bphilipnyc指出这一点):

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class StartupHousekeeper {

  @EventListener(ContextRefreshedEvent.class)
  public void contextRefreshedEvent() {
    // do whatever you need here 
  }
}

答案 2 :(得分:33)

在Spring 4.2+中你现在可以做到:

@Component
class StartupHousekeeper {

    @EventListener(ContextRefreshedEvent.class)
    void contextRefreshedEvent() {
        //do whatever
    }
}

答案 3 :(得分:9)

对于在尝试引用@PostConstruct注释时收到警告的Java 1.8用户,我最终捎带了@Scheduled注释,如果你已经有一个带有fixedRate或fixedDelay的@Scheduled作业,你可以这样做。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling
@Component
public class ScheduledTasks {

private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class);

private static boolean needToRunStartupMethod = true;

    @Scheduled(fixedRate = 3600000)
    public void keepAlive() {
        //log "alive" every hour for sanity checks
        LOGGER.debug("alive");
        if (needToRunStartupMethod) {
            runOnceOnlyOnStartup();
            needToRunStartupMethod = false;
        }
    }

    public void runOnceOnlyOnStartup() {
        LOGGER.debug("running startup job");
    }

}

答案 4 :(得分:9)

如果你使用的是弹簧靴,这是最好的答案。

我觉得@PostConstruct和其他各种生命周期的插入都是关于方式的。这些可能直接导致运行时问题或由于意外的bean /上下文生命周期事件而导致不明显的缺陷。为什么不直接使用普通Java调用bean?你仍然用'spring way'调用bean(例如:通过spring AoP代理)。最重要的是,它是普通的java,不能比这更简单。不需要上下文侦听器或奇怪的调度程序。

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext app = SpringApplication.run(DemoApplication.class, args);

        MyBean myBean = (MyBean)app.getBean("myBean");

        myBean.invokeMyEntryPoint();
    }
}

答案 5 :(得分:7)

我们所做的是在上下文开始时将org.springframework.web.context.ContextLoaderListener扩展为打印内容。

public class ContextLoaderListener extends org.springframework.web.context.ContextLoaderListener
{
    private static final Logger logger = LoggerFactory.getLogger( ContextLoaderListener.class );

    public ContextLoaderListener()
    {
        logger.info( "Starting application..." );
    }
}

然后在web.xml

中配置子类
<listener>
    <listener-class>
        com.mycomp.myapp.web.context.ContextLoaderListener
    </listener-class>
</listener>

答案 6 :(得分:3)

  

注意,只有在您的runOnceOnStartup方法取决于a时,才会建议您这样做   完全初始化的春天背景。例如:你想打电话给dao   与交易划分

您还可以使用fixedDelay设置得非常高的预定方法

@Scheduled(fixedDelay = Long.MAX_VALUE)
public void runOnceOnStartup() {
    dosomething();
}

这有利于整个应用程序连线(Transactions,Dao,...)

见于Scheduling tasks to run once, using the Spring task namespace

答案 7 :(得分:3)

借助SpringBoot,我们可以在启动时通过v2注释执行方法

1

答案 8 :(得分:1)

发布另一个实现WebApplicationInitializer的解决方案,在实例化任何spring bean之前调用它,以防有人拥有该用例

Initialize default Locale and Timezone with Spring configuration

答案 9 :(得分:1)

{{1}}

答案 10 :(得分:0)

如果要在应用程序完全运行之前配置bean,可以使用@Autowired

@Autowired
private void configureBean(MyBean: bean) {
    bean.setConfiguration(myConfiguration);
}

答案 11 :(得分:0)

您可以在组件上使用@EventListener,这将在服务器启动并初始化所有bean后调用。

@EventListener
public void onApplicationEvent(ContextClosedEvent event) {

}

答案 12 :(得分:0)

有关一个文件StartupHousekeeper.java位于包com.app.startup

StartupHousekeeper.java中执行此操作:

@Component
public class StartupHousekeeper {

  @EventListener(ContextRefreshedEvent.class)
  public void keepHouse() {
    System.out.println("This prints at startup.");
  }
}

然后在myDispatcher-servlet.java中执行此操作:

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <mvc:annotation-driven />
    <context:component-scan base-package="com.app.startup" />

</beans>