在春季启动时执行方法

当应用程序第一次启动时,是否有Spring 3的特性来执行某些方法? 我知道我可以使用@Scheduled注释来设置一个方法,它会在启动之后执行,但是它会定期执行。

谢谢。

如果通过“应用程序启动”的意思是“应用程序上下文启动”,那么是的,有很多方法可以做到这一点 ,最简单的(对于单身bean,无论如何)是用@PostConstruct注释你的方法。 看看链接,看看其他选项,但总的来说他们是:

  • @PostConstruct注解的方法
  • InitializingBeancallback接口定义的afterPropertiesSet()
  • 自定义configuration的init()方法

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

如果您需要专门挂接上下文启动/closures,那么您可以实现Lifecycle界面 ,但这可能是不必要的。

这很容易用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中同步运行。 如果你想确保你的代码只执行一次,只要在你的组件中保持一些状态即可。

UPDATE

从Spring @EventListener开始,您还可以使用@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 } } 

在4.2 +你现在可以简单地做:

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

对于在试图引用@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"); } } 

如果你正在使用弹簧启动,这是最好的答案。

我觉得@PostConstruct和其他各种生命周期的感叹词都是四面八方的。 这些可能会直接导致运行时问题,或者由于意外的bean /上下文生命周期事件而导致不明显的缺陷。 为什么不直接用普通的Java调用你的bean呢? 你仍然调用bean的“spring的方式”(例如:通过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(); } } 

我们所做的就是扩展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.xmlconfiguration子类:

 <listener> <listener-class> com.mycomp.myapp.web.context.ContextLoaderListener </listener-class> </listener> 

注意,只有在runOnceOnStartup方法依赖于完全初始化的spring上下文runOnceOnStartup 。 例如:你要用事务划分来调用一个dao

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

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

这有一个好处,整个应用程序连线(交易,道,…)

在使用Spring任务命名空间调度任务运行一次中看到

发布了另一个实现了WebApplicationInitializer的解决scheme,并且在任何spring bean实例化之前被调用,以防有人拥有该用例

使用Springconfiguration初始化默认的Locale和Timezone

如果要在应用程序运行完毕之前configuration一个bean,可以使用@Autowired

 @Autowired private void configureBean(MyBean: bean) { bean.setConfiguration(myConfiguration); } 
 AppStartListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof ApplicationReadyEvent){ System.out.print("ciao"); } } }