第一次启动应用程序时,是否有任何Spring 3功能可以执行某些方法?我知道我可以设置一个带@Scheduled
注释的方法,然后在启动后执行,但它会定期执行。
答案 0 :(得分:175)
如果“应用程序启动”是指“应用程序上下文启动”,那么是的,有many ways to do this,最简单的(对于单例bean,无论如何)要用@PostConstruct
注释您的方法。看一下链接以查看其他选项,但总的来说它们是:
@PostConstruct
afterPropertiesSet()
由InitializingBean
回调接口定义
从技术上讲,它们是 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>