2017-07-24 179 views
2

是否有可能在應用程序啓動時運行一個類時mvc 我想初始化該類中的線程?在spring-mvc應用程序啓動時運行一個類

還是有什麼辦法..?

   public class MyServletContextListener implements Runnable { 



      public void run() { 

       while (true) { 

       try { 
        System.out.println("Inside run()"); 
        Thread.sleep(10000); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       } 


      } 

      } 

這種輸出增加ApplicationListener接口的

  NFO: HHH000206: hibernate.properties not found 
      Jul 24, 2017 8:42:33 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit> 
      INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final} 
      Jul 24, 2017 8:42:35 PM org.hibernate.dialect.Dialect <init> 
      INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 
      Jul 24, 2017 8:42:36 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation 
      INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4 

      Thread Started 
      getApplicationName() : /Hibernate_webservice 
      getId() : org.springframework.web.context.WebApplicationContext:/Hibernate_webservice 
      getParent() : null 
      getDisplayName() : Root WebApplicationContext 


      Jul 24, 2017 8:42:38 PM org.springframework.web.context.ContextLoader initWebApplicationContext 
      INFO: Root WebApplicationContext: initialization completed in 8880 ms 
      Jul 24, 2017 8:42:38 PM org.apache.catalina.core.ApplicationContext log 
      INFO: Initializing Spring FrameworkServlet 'appServlet' 
      Jul 24, 2017 8:42:38 PM org.springframework.web.servlet.DispatcherServlet initServletBean 
      INFO: FrameworkServlet 'appServlet': initialization started 
      Jul 24, 2017 8:42:38 PM org.springframework.web.context.support.XmlWebApplicationContext prepareRefresh 
      INFO: Refreshing WebApplicationContext for namespace 'appServlet-servlet': startup date [Mon Jul 24 20:42:38 IST 2017]; parent: Root WebApplicationContext 
      Jul 24, 2017 8:42:38 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 
      INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring-config.xml] 
      Jul 24, 2017 8:42:38 PM org.springframework.context.support.PropertySourcesPlaceholderConfigurer loadProperties 
      INFO: Loading properties file from class path resource [application.properties] 
      Jul 24, 2017 8:42:38 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 
      INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring 
      Jul 24, 2017 8:42:38 PM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping registerHandlerMethod 
      INFO: Mapped "{[/form],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView sample.test.TestController.method() 
      Jul 24, 2017 8:42:39 PM org.hibernate.dialect.Dialect <init> 
      INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 
      Jul 24, 2017 8:42:39 PM org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl useContextualLobCreation 
      INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4 

      Thread Started 
      getApplicationName() : /Hibernate_webservice 
      getId() : org.springframework.web.context.WebApplicationContext:/Hibernate_webservice/appServlet 
      getParent() : Root WebApplicationContext: startup date [Mon Jul 24 20:42:30 IST 2017]; root of context hierarchy 
      getDisplayName() : WebApplicationContext for namespace 'appServlet-servlet' 



      Thread Started 
      getApplicationName() : /Hibernate_webservice 
      getId() : org.springframework.web.context.WebApplicationContext:/Hibernate_webservice/appServlet 
      getParent() : Root WebApplicationContext: startup date [Mon Jul 24 20:42:30 IST 2017]; root of context hierarchy 
      getDisplayName() : WebApplicationContext for namespace 'appServlet-servlet' 


      Jul 24, 2017 8:42:39 PM org.springframework.web.servlet.DispatcherServlet initServletBean 
      INFO: FrameworkServlet 'appServlet': initialization completed in 1365 ms 
      Jul 24, 2017 8:42:40 PM org.apache.coyote.AbstractProtocol start 
      INFO: Starting ProtocolHandler ["http-nio-8082"] 
      Jul 24, 2017 8:42:40 PM org.apache.coyote.AbstractProtocol start 
      INFO: Starting ProtocolHandler ["ajp-nio-8011"] 
      Jul 24, 2017 8:42:40 PM org.apache.catalina.startup.Catalina start 
      INFO: Server startup in 19807 ms 

回答

2

春節後,我得到了提供ApplicationListener<ContextRefreshedEvent>接口及其onApplicationEvent(ContextRefreshedEvent event)鉤。

例如:

@Component 
public class MyServiceCreationListener implements ApplicationListener<ContextRefreshedEvent> { 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 
     // do something on container startup 
    } 
} 

無論你在onApplicationEvent方法寫會被執行一次且僅一次創建Spring上下文時。

如果您發現此方法被多次調用,那麼您必須具有多個ApplicationContext。如果你檢查event.getApplicationContext()你可能會看到他們每個人都有一個不同的ID和displayName,你可以找出他們的起源。如果你的是Spring MVC應用程序,那麼你可能同時擁有一個ContextLoaderListenerDispatcherServlet,這兩個都創建它們自己的ApplicationContext,每個都會觸發一個ContextRefreshedEvent

如果你想確定哪個是父上下文,你可以嘗試event.getApplicationContext().getParent() != null,或者你可以在你的ApplicationListener中切換一個布爾類,例如: alreadyInitialised

還有Spring 4的SmartInitializingSingleton這可能允許您掛鉤到不同級別的上下文創建。

+0

此解決方案正在工作,但它在應用程序加載時調用onApplicationEvent(ContextRefreshedEvent event)3次 –

+0

我已經更新了答案,以描述如何多次觸發ContextRefreshedEvent並提供有關如何避免/處理該問題的一些建議。 – glytching

+0

有多個應用程序上下文是很好的...如果我只需要一個上下文,該怎麼辦? –

0

通過擴展Thread創建一個簡單的Java線程,並由Spring的容器通過@Component.管理。bean的範圍必須是「prototype」,以便每個請求都會返回一個新實例,以運行每個單獨的線程。

PrintThread.java: 

package com.mkyong.thread; 

import org.springframework.context.annotation.Scope; 
import org.springframework.stereotype.Component; 

@Component 
@Scope("prototype") 
public class PrintThread extends Thread{ 

    @Override 
    public void run() { 

     System.out.println(getName() + " is running"); 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(getName() + " is running"); 
    } 

} 

AppConfig.java: 

package com.mkyong.config; 

import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 

@Configuration 
@ComponentScan(basePackages="com.mkyong.thread") 
public class AppConfig{ 
} 

App.java: 

package com.mkyong; 

import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 

import com.mkyong.config.AppConfig; 
import com.mkyong.thread.PrintThread; 

public class App 
{ 
    public static void main(String[] args) 
    { 

     ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); 

     PrintThread printThread1 = (PrintThread) ctx.getBean("printThread"); 
     printThread1.setName("Thread 1"); 

     PrintThread printThread2 = (PrintThread) ctx.getBean("printThread"); 
     printThread2.setName("Thread 2"); 

     PrintThread printThread3 = (PrintThread) ctx.getBean("printThread"); 
     printThread3.setName("Thread 3"); 

     PrintThread printThread4 = (PrintThread) ctx.getBean("printThread"); 
     printThread4.setName("Thread 4"); 

     PrintThread printThread5 = (PrintThread) ctx.getBean("printThread"); 
     printThread5.setName("Thread 5"); 

     printThread1.start(); 
     printThread2.start(); 
     printThread3.start(); 
     printThread4.start(); 
     printThread5.start(); 

    } 
} 

輸出 - 訂貨會,每次變化,這是線程:)

Thread 3 is running 
Thread 2 is running 
Thread 1 is running 
Thread 5 is running 
Thread 4 is running 
Thread 2 is running 
Thread 4 is running 
Thread 5 is running 
Thread 3 is running 
Thread 1 is running 

希望這有助於:)

2

您可以添加應用程序監聽器(A類實現上下文監聽器接口)創建你的線程沒有頭痛 如果你正在創建時間表,你可以使用石英或彈簧計時器