답변:
"응용 프로그램 시작"이 "응용 프로그램 컨텍스트 시작"을 의미하는 경우 그렇습니다.이 작업을 수행 하는 가장 쉬운 방법 은 여러 가지 가 @PostConstruct
있습니다. 다른 옵션을 보려면 링크를 살펴보십시오. 요약하면 다음과 같습니다.
@PostConstruct
afterPropertiesSet()
InitializingBean
콜백 인터페이스에 의해 정의 된기술적으로 이들은 컨텍스트 라이프 사이클이 아닌 Bean 라이프 사이클에 연결되지만 99 %의 경우 두 가지가 동일합니다.
컨텍스트 시작 / 종료에 구체적으로 연결해야하는 경우 대신 인터페이스 를 구현할Lifecycle
수 있지만 불필요 할 수 있습니다 .
Access restriction: The type PostConstruct is not accessible due to restriction on required library /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home/jre/lib/rt.jar
@PostConstruct
메소드가 호출되었지만 간접적으로 의존했던 JMS 인프라는 아직 완전히 연결되지 않았다 (그리고 Spring은 모든 것이 조용히 실패했다). @EventListener(ApplicationReadyEvent.class)
모든 작업으로 전환하면 ( ApplicationReadyEvent
바닐라 스프링에 대한 스프링 부트는 스테판의 답변 참조).
이것은로 쉽게 수행 할 수 있습니다 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
}
}
ContextStartedEvent
대신 NB를 사용하려는 사람들 은 이벤트가 발생하기 전에 리스너를 추가하기가 더 어렵습니다.
Spring 4.2 이상에서는 이제 간단하게 할 수 있습니다.
@Component
class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
//do whatever
}
}
스프링 부트를 사용하는 경우 이것이 가장 좋은 대답입니다.
나는 느낌 @PostConstruct
등 다양한 수명주기 감탄사가 라운드에 대한 방법입니다합니다. 이로 인해 런타임 문제가 직접 발생하거나 예기치 않은 Bean / 컨텍스트 라이프 사이클 이벤트로 인해 눈에 띄지 않는 결함이 발생할 수 있습니다. 왜 일반 Java를 사용하여 Bean을 직접 호출하지 않습니까? 당신은 여전히 빈을 'spring way'(예 : 스프링 AoP 프록시를 통해) 호출합니다 그리고 무엇보다도, 그것은 평범한 자바이며, 그보다 더 간단해질 수는 없습니다. 컨텍스트 리스너 나 홀수 스케줄러가 필요하지 않습니다.
@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();
}
}
main()
애플리케이션 프레임 워크 (예 : JavaServer Faces)를 사용할 때와 같은 다른 시나리오도 없습니다 .
@PostConstruct 주석을 참조하려고 할 때 경고가 표시되는 Java 1.8 사용자의 경우, fixedRate 또는 fixedDelay를 사용하여 @Scheduled 작업이 이미있는 경우 수행 할 수있는 @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>
SpringBoot를 사용하면 시작시 @EventListener
주석을 통해 메소드를 실행할 수 있습니다
@Component
public class LoadDataOnStartUp
{
@EventListener(ApplicationReadyEvent.class)
public void loadData()
{
// do something
}
}
주의 : 이것은
runOnceOnStartup
메소드가 완전히 초기화 된 스프링 컨텍스트에 의존하는 경우에만 권장됩니다 . 예를 들어, 트랜잭션 경계 설정이있는 dao를 호출하려고합니다.
fixedDelay를 매우 높게 설정하여 예약 된 방법을 사용할 수도 있습니다.
@Scheduled(fixedDelay = Long.MAX_VALUE)
public void runOnceOnStartup() {
dosomething();
}
이것은 전체 응용 프로그램이 연결되어 있다는 이점이 있습니다 (Transactions, Dao, ...)
Spring 작업 네임 스페이스를 사용하여 한 번 실행되도록 예약 작업 에서 볼 수 있음
@PostConstruct
않습니까?
WebApplicationInitializer를 구현하고 누군가가 유스 케이스를 가지고있는 경우 스프링 빈이 인스턴스화되기 훨씬 전에 호출되는 다른 솔루션을 게시했습니다.
AppStartListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ApplicationReadyEvent){
System.out.print("ciao");
}
}
}
@EventListener
서버에서 시작되고 모든 Bean이 초기화 된 후에 호출되는 컴포넌트에서 사용할 수 있습니다 .
@EventListener
public void onApplicationEvent(ContextClosedEvent event) {
}
StartupHousekeeper.java
package에 있는 파일의 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>