2014-12-10 6 views
71

스프링 부트 앱이 변경 사항을 위해 디렉토리를 모니터링하기 시작한 후 코드를 실행하고 싶습니다.봄 부팅 후 코드 실행

새 스레드를 실행하려고 시도했지만 그 시점에서 @Autowired 서비스가 설정되지 않았습니다.

ApplicationPreparedEvent을 찾을 수 있었으며 @Autowired 특수 효과가 설정되기 전에 실행되었습니다. 응용 프로그램이 HTTP 요청을 처리 할 준비가되면 이상적으로 이벤트를 발생시키고 싶습니다.

응용 프로그램을 실행 한 후에 더 좋은 방법으로 코드를 실행 하시겠습니까? spring-boot?

답변

45

시도 :

@Configuration 
@EnableAutoConfiguration 
@ComponentScan 
public class Application extends SpringBootServletInitializer { 

    @SuppressWarnings("resource") 
    public static void main(final String[] args) { 
     ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); 

     context.getBean(Table.class).fillWithTestdata(); // <-- here 
    } 
} 
+0

이 훌륭한 기능! 이제 테이블 엔티티에 서비스를 호출하는 메소드가 있습니다. – stewsters

+1

웹 서버 배포에는 작동하지 않습니다. –

+2

응용 프로그램을 warcat 파일로 외부 tomcat에 배포 할 때이 기능이 작동하지 않습니다. 임베디드 톰캣에서만 작동합니다. – Saurabh

62

이유는 단지 같은 초기화에 모니터를 시작 콩, 뭔가를 만들 수 없습니다 : 어떤에서 autowiring이 수행됩니다 때까지 init 메서드가 호출되지 않습니다

@Component 
public class Monitor { 
    @Autowired private SomeService service 

    @PostConstruct 
    public void init(){ 
     // start your monitoring in here 
    } 
} 

콩.

+6

'@ PostConstruct'가 너무 일찍 시작되는 경우가 있습니다. 예를 들어 Spring Cloud Stream Kafka를 사용할 때 애플리케이션이 Kafka에 바인딩되기 전에'@ PostConstruct'가 실행됩니다. Dave Syer의 솔루션은시기 적절하게 발생하므로 더 좋습니다. –

+1

'@ PostConstruct'는 초기화 과정에서 발생합니다. 일부 경우에 유용 할 수 있지만 ** Spring Boot가 시작된 후 **를 실행하려면 정답이 아닙니다. 예를 들어,'@ PostConstruct'가 끝나지 않는 동안에는 어떤 끝점도 사용할 수 없습니다. – cahen

41

"봄 부팅"방법은 CommandLineRunner을 사용하는 것입니다. 그 유형의 콩을 추가하면 잘 갈 수 있습니다. Spring 4.1 (Boot 1.2)에는 모든 것이 초기화 된 후에 콜백을 얻는 SmartInitializingBean도 있습니다. 그리고 SmartLifecycle (봄 3부터)이 있습니다.

+0

그 중 어떤 예입니까? 임의의 순간에 명령 행을 통해 앱이 실행 된 후에 빈을 실행할 수 있습니까? – Emilio

+2

"임의의 순간"이 무슨 뜻인지 몰라. 스프링 부트 사용자 가이드와 샘플은'CommandLineRunner' (그리고 더 새로운'ApplicationRunner')를 사용하는 예제를 가지고 있습니다 : http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot -features-command-line-runner입니다. –

+0

Lifecycle은 응용 프로그램의 시작/중지 단계에서 비동기 작업을 수행하기 위해 선호되는 옵션이며 CommandLineRunner와 InitializingBeans 간의 다른 차이점을 찾아 내려고했지만 그 점에 대해서는 아무 것도 찾을 수 없습니다. – saljuama

44

ApplicationReadyEvent를 사용해 보셨습니까?

@Component 
public class ApplicationStartup 
implements ApplicationListener<ApplicationReadyEvent> { 

    /** 
    * This event is executed as late as conceivably possible to indicate that 
    * the application is ready to service requests. 
    */ 
    @Override 
    public void onApplicationEvent(final ApplicationReadyEvent event) { 

    // here your code ... 

    return; 
    } 
} 

코드에서 : http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

이것은 documentation이 시작 이벤트에 대한 언급 것입니다 :

...

응용 프로그램 이벤트로, 다음과 같은 순서로 전송하여 응용 프로그램 실행 :

ApplicationStartedEvent가 실행이 시작되었지만 청취자와 이니셜 라이저 등록을 제외한 모든 처리는 이전입니다.

컨텍스트에서 사용할 환경이 알려져 있지만 컨텍스트 이 만들어지기 전에 ApplicationEnvironmentPreparedEvent가 전송됩니다.

ApplicationPreparedEvent는 새로 고침이 시작되기 직전이지만 Bean 정의가로드 된 후에 전송됩니다.

새로 고침 후에 ApplicationReadyEvent가 전송되고 관련 콜백이 처리되어 응용 프로그램이 서비스 요청 준비가되었음을 나타냅니다.

시작시 예외가 있으면 ApplicationFailedEvent가 전송됩니다.

...

+7

또 다른 방법으로, Bean 메소드에서'''@ EventListener''' 주석을 사용하여 연결할 수 있습니다.이 메소드는 후크하려는 클래스 이벤트를 인수로 전달합니다. – padilo

+0

이것은 선택된 답변이어야합니다. – varun113

17

ApplicationRunner을 사용하여 클래스를 확장하고 run() 메서드를 재정 의하여 코드를 추가 할 수 있습니다. 대안 CommandLineRunner 콩이 될 수

@Component 
public class CommandLineAppStartupRunner implements CommandLineRunner { 
    private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class); 

    @Override 
    public void run(String...args) throws Exception { 
     logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args)); 
    } 
} 
1

bean 메소드를 @PostConstruct으로 구현하거나 주석을 달았습니다.

@Configuration 
public class ProjectConfiguration { 
    private static final Logger log = 
    LoggerFactory.getLogger(ProjectConfiguration.class); 

    @EventListener(ApplicationReadyEvent.class) 
    public void doSomethingAfterStartup() { 
    log.info("hello world, I have just started up"); 
    } 
} 
2

봄> 4.1

@Bean 
public SmartInitializingSingleton importProcessor() { 
    return() -> { 
     doStuff(); 
    }; 

} 

SmartInitializingSingleton 콩을 사용하여 마법처럼 일했다 데이브 Syer 응답에 대한 예를 제공

import org.springframework.boot.ApplicationRunner; 

@Component 
public class ServerInitializer implements ApplicationRunner { 

    @Override 
    public void run(ApplicationArguments applicationArguments) throws Exception { 

     //code goes here 

    } 
} 
40

그것은이만큼이나 간단합니다 올바른 서버 작동에 대한 요구 사항이 아닙니다. 변경 사항을 모니터하기 위해 비동기 태스크를 시작하는 것이 좋은 예입니다. 작업이 당신이 전에 REST 포트가 열려 콜백을받을 것이기 때문에 SmartInitializingSingleton을 구현하는 것이 좋습니다 다음 완료 될 때까지

경우, 그러나 서버는 '준비되지 않음'상태에 있고 서버가 열려 있습니다 사업.

한 번만 발생해야하는 작업에 @PostConstruct을 사용하지 않으려 고하십시오. 여러 번 호출되는 것을 발견하면 무례한 놀라움을 느낄 것입니다 ...

+3

감사합니다. 이로 인해 변경 작업 없이도 코드 작업이 가능해졌습니다. 이렇게 간단한 대답에 다시 한번 감사드립니다. @RequestMapping 주석에도 문제없이 사용할 수 있습니다. – Harshit

+0

누군가는 @EventListener (ContextRefreshedEvent.class)를 대신 사용하고자 할 수도 있습니다. 이것은 빈 생성 후, 서버가 시작되기 전에 트리거됩니다. 모든 요청이 서버에 도달하기 전에 활동을 수행하는 데 사용할 수 있습니다. – neeraj

+1

@neeraj, 질문은 스프링 부트가 시작된 후 코드를 실행하는 것에 관한 것입니다. 'ContextRefreshedEvent'를 사용하면 모든 새로 고침 후에도 실행됩니다. – cahen

1

ApplicationReadyEvent가 수행 할 작업 인 경우 정말 유용하다 :

@EventListener(ApplicationReadyEvent.class) 
public void doSomethingAfterStartup() { 
    System.out.println("hello world, I have just started up"); 
} 

봄 구성을 버전 1.5.1.RELEASE