在Spring中启动时执行方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Spring中启动时执行方法相关的知识,希望对你有一定的参考价值。
当应用程序第一次启动时,是否有任何Spring 3功能可以执行某些方法?我知道我可以使用@Scheduled
注释设置方法,并在启动后立即执行,但随后会定期执行。
如果通过“应用程序启动”你的意思是“应用程序上下文启动”,那么是的,有many ways to do this,最简单的(对于单身豆,无论如何)是用@PostConstruct
注释你的方法。看一下链接以查看其他选项,但总的来说它们是:
- 用
@PostConstruct
注释的方法 afterPropertiesSet()
由InitializingBean
回调接口定义- 自定义配置的init()方法
从技术上讲,这些是bean生命周期的钩子,而不是上下文生命周期,但在99%的情况下,这两者是等价的。
如果你需要专门挂钩上下文启动/关闭,那么你可以改为implement the Lifecycle
interface,但这可能是不必要的。
Initialize default Locale and Timezone with Spring configuration
如果要在应用程序完全运行之前配置bean,可以使用AppStartListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ApplicationReadyEvent){
System.out.print("ciao");
}
}
}
:
@Autowired
您可以在组件上使用@Autowired
private void configureBean(MyBean: bean) {
bean.setConfiguration(myConfiguration);
}
,这将在服务器启动并初始化所有bean后调用。
@EventListener
对于位于包@EventListener
public void onApplicationEvent(ContextClosedEvent event) {
}
的文件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
这很容易用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 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
}
}
在Spring 4.2+中,你现在可以简单地做到:
@Component
class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
void contextRefreshedEvent() {
//do whatever
}
}
如果你使用弹簧靴,这是最好的答案。
我觉得@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();
}
}
对于在尝试引用@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");
}
}
我们所做的是扩展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>
使用Spring Boot,我们可以通过qazxsw poi annotation在启动时执行一个方法
@EventListener
请注意,仅在您的
@Component public class LoadDataOnStartUp { @EventListener(ApplicationReadyEvent.class) public void loadData() { // do something } }
方法依赖于完全初始化的弹簧上下文时才建议这样做。例如:你想用事务划分来调用dao
您还可以使用fixedDelay设置得非常高的预定方法
runOnceOnStartup
这有利于整个应用程序连线(Transactions,Dao,...)
在@Scheduled(fixedDelay = Long.MAX_VALUE)
public void runOnceOnStartup() {
dosomething();
}
看到
发布另一个实现WebApplicationInitializer的解决方案,在实例化任何spring bean之前调用很多,以防有人拥有该用例
Scheduling tasks to run once, using the Spring task namespace
以上是关于在Spring中启动时执行方法的主要内容,如果未能解决你的问题,请参考以下文章
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式