स्प्रिंग बूट शुरू होने के बाद कोड चलाना


211

मैं अपने स्प्रिंग-बूट के बाद कोड चलाना चाहता हूं एप्लिकेशन को परिवर्तनों के लिए एक निर्देशिका की निगरानी शुरू करने ।

मैंने एक नया सूत्र चलाने की कोशिश की है, लेकिन @Autowiredउस बिंदु पर सेवाएं निर्धारित नहीं की गई हैं।

मैं खोजने में सक्षम रहा हूं ApplicationPreparedEvent, जो @Autowiredएनोटेशन सेट होने से पहले आग लगाते हैं। आदर्श रूप से मैं घटना को आग लगाना चाहूंगा, एक बार आवेदन http अनुरोधों को संसाधित करने के लिए तैयार है।

क्या स्प्रिंग-बूट में एप्लिकेशन के लाइव होने के बाद उपयोग करने के लिए एक बेहतर घटना है, या कोड चलाने का एक बेहतर तरीका है ?



स्प्रिंग बूट दो इंटरफेस देता है ApplicationRunner और CommandLineRunner का उपयोग तब किया जा सकता है जब आप स्प्रिंग शुरू होने के बाद कोड चलाना चाहते हैं। कार्यान्वयन उदाहरण के लिए आप इस लेख को देख सकते हैं - jhooq.com/applicationrunner-spring-boot
राहुल वाघ

जवाबों:


121

प्रयत्न:

@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
    }
}

6
यह तब काम नहीं करता है जब आप किसी बाहरी टॉमकट में युद्ध फ़ाइल के रूप में आवेदन को तैनात करते हैं। यह केवल एम्बेडेड टॉमकैट के साथ काम करता है
सौरभ

नहीं, यह काम नहीं करता है। लेकिन इस उपयोग के मामले में मुझे इसके बजाय अधिक स्पष्ट तरीका पसंद है @Component। युद्ध फ़ाइल में इसे प्राप्त करने के लिए @cjstehno से उत्तर देखें।
एंटोन बेसोनोव

320

यह इस तरह सरल है:

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

संस्करण पर परीक्षण किया गया 1.5.1.RELEASE


7
धन्यवाद। इसने बिना किसी बदलाव के मेरा कोड काम कर दिया। इस तरह के एक सरल जवाब के लिए फिर से धन्यवाद। यह बिना किसी समस्या के @RequestMapping एनोटेशन के साथ भी काम करेगा।
हर्षित

16
कोई @EventListener(ContextRefreshedEvent.class)इसके बजाय उपयोग करने की इच्छा कर सकता है , जो बीन निर्माण के बाद ट्रिगर हो जाता है, लेकिन सर्वर शुरू होने से पहले। यह सर्वर से किसी भी अनुरोध को हिट करने से पहले गतिविधियों को करने के लिए इस्तेमाल किया जा सकता है।
नीरज

3
@ नीरज, सवाल स्प्रिंग बूट शुरू होने के बाद कोड चलाने के बारे में है। यदि आप उपयोग करते हैं ContextRefreshedEvent, तो यह हर रिफ्रेश के बाद भी चलेगा।
काहेन

4
स्प्रिंग बूट 2.0.5 पर परीक्षण किया गया। कृपया
रितेश

2
2.2.2 रिलीज पर परीक्षण किया गया। यह पूरी तरह से काम करता है। यह समाधान मेरा समय बचाता है।
अरफिले

96

क्या आपने 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-bartup/

यह वही है जो प्रलेखन स्टार्टअप घटनाओं के बारे में बताता है:

...

आपके आवेदन के चलते ही एप्लिकेशन ईवेंट निम्न क्रम में भेजे जाते हैं:

ApplicationStartedEvent एक रन की शुरुआत में भेजा जाता है, लेकिन श्रोताओं और शुरुआती लोगों के पंजीकरण को छोड़कर किसी भी प्रसंस्करण से पहले।

एक ApplicationEnvironmentPreparedEvent भेजा जाता है जब संदर्भ में पर्यावरण का उपयोग किया जाना है, लेकिन संदर्भ बनने से पहले।

रिफ्रेश शुरू होने से ठीक पहले एक ApplicationPreparedEvent भेजा जाता है, लेकिन बीन की परिभाषाओं को लोड करने के बाद।

एक ApplicationReadyEvent रिफ्रेश होने के बाद भेजा जाता है और किसी भी संबंधित कॉलबैक को संसाधित करने के लिए संकेत दिया जाता है कि आवेदन सेवा अनुरोधों के लिए तैयार है।

यदि स्टार्टअप पर कोई अपवाद है, तो ApplicationFailedEvent भेजा जाता है।

...


11
एक विकल्प के रूप में, आप @EventListenerएक बीन विधि पर एनोटेशन का उपयोग करके ऐसा कर सकते हैं , जिस तर्क को आप जिस क्लास इवेंट में हुक करना चाहते हैं, के रूप में पास करना।
पैडिलो

2
यह चुना हुआ उत्तर होना चाहिए।
varun113

2
यह स्प्रिंग-बूट 2 में बदल गया है। यदि आप 1.x से पोर्ट कर रहे हैं और ApplicationStartedEvent का उपयोग कर रहे हैं तो आप अब इसके बजाय ApplicationStartingEvent चाहते हैं।
एंडी ब्राउन

यह बिल्कुल ठीक काम करता है और मुझे लगता है कि सबसे अच्छा तरीका है।
AVINASH SHRIMALI

आप सबसे अच्छे हैं
acm

83

क्यों न केवल एक बीन तैयार किया जाए जो प्रारंभ पर आपके मॉनिटर को शुरू करता है, कुछ इस प्रकार है:

@Component
public class Monitor {
    @Autowired private SomeService service

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

initजब तक किसी भी autowiring सेम के लिए किया जाता विधि कहा जाता है नहीं किया जाएगा।


14
कभी-कभी @PostConstructबहुत जल्दी आग लग जाती है। उदाहरण के लिए, स्प्रिंग क्लाउड स्ट्रीम काफ्का का उपयोग करते समय, @PostConstructआवेदन करने से पहले आग लग जाती है। डेव सीरर का समाधान बेहतर है क्योंकि यह समय पर फायर करता है।
एलेन अब्दुर्रखिमोव

9
@PostConstructआरंभीकरण के दौरान होता है, बाद में नहीं। हालांकि यह कुछ मामलों में उपयोगी हो सकता है, यह सही उत्तर नहीं है यदि आप स्प्रिंग बूट शुरू होने के बाद चलाना चाहते हैं । उदाहरण के लिए, @PostConstructसमाप्त नहीं होने पर, कोई भी समापन बिंदु उपलब्ध नहीं हैं।
कहेन

63

"स्प्रिंग बूट" तरीका एक का उपयोग करना है CommandLineRunner। बस उस प्रकार की फलियां जोड़ें और आप जाने के लिए अच्छे हैं। स्प्रिंग 4.1 (बूट 1.2) में वह भी है SmartInitializingBeanजो सब कुछ शुरू होने के बाद कॉलबैक हो जाता है। और वहाँ SmartLifecycle(वसंत 3 से) है।


उसका कोई उदाहरण? क्या ऐप चलाने के बाद सेम को निष्पादित करना संभव है, एक मनमाना क्षण में कमांड लाइन के माध्यम से?
एमिलियो

5
पता नहीं क्या आप "मनमाना पल" से मतलब है। स्प्रिंग बूट उपयोगकर्ता गाइड और नमूनों में CommandLineRunner(और नए ApplicationRunner): docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/… का उपयोग करने के उदाहरण हैं ।
डेव सीयर

मैंने पाया, कि जीवनचक्र अनुप्रयोग के प्रारंभ / पड़ाव चरणों पर अतुल्यकालिक कार्य करने के लिए पसंदीदा विकल्प है, और मैं कमांडलाइनरनर और इनिशियलाइज़िंग बीन्स के बीच अन्य अंतरों को पहचानने की कोशिश कर रहा हूं, लेकिन इसके बारे में कुछ भी पता नहीं लगा सकता।
सलजूमा

3
युगल सामान्य उदाहरण कोड का उपयोग करते हुएCommandLineRunner
एलेक्सी साइमनोव

41

आप एक वर्ग का उपयोग करके विस्तार कर सकते हैं ApplicationRunner, run()विधि को ओवरराइड कर सकते हैं और वहां कोड जोड़ सकते हैं।

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {

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

        //code goes here

    }
}

स्प्रिंग बूट में बिल्कुल सही। वर्ग के लिए ApplicationScope होने पर रन () विधि को दो बार कहा जाता था। तो ऊपर के साथ PostConstruct मेथड ने बेहतर काम किया।
सैम

26

ApplicationReadyEventवास्तव में केवल तभी उपयोगी होता है जब आप जिस कार्य को करना चाहते हैं वह सही सर्वर ऑपरेशन की आवश्यकता नहीं है। परिवर्तनों के लिए कुछ की निगरानी करने के लिए एक async कार्य शुरू करना एक अच्छा उदाहरण है।

यदि, हालांकि आपका सर्वर कार्य पूरा नहीं होने तक 'तैयार नहीं' स्थिति में है, तो इसे लागू करना बेहतर है SmartInitializingSingletonक्योंकि आपके REST पोर्ट को खोलने से पहले आपको कॉलबैक मिल जाएगा और आपका सर्वर व्यवसाय के लिए खुला है।

उन @PostConstructकार्यों के लिए उपयोग करने के लिए परीक्षा न करें जो केवल एक बार ही होने चाहिए। जब आप इसे कई बार बुलाया जा रहा है, तो आपको आश्चर्य होगा कि आपको आश्चर्य होगा ...


यह चुना हुआ उत्तर होना चाहिए। जैसा कि @Andy बताते हैं, बंदरगाहों के खुलने से ठीक पहले SmartInitializingSingleton कहा जाता है।
श्रीकांत

24

वसंत विन्यास के साथ:

@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");
  }
}

12

SmartInitializingSingletonवसंत में एक सेम का उपयोग करें > 4.1

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

}

विकल्प के रूप में एक CommandLineRunnerबीन को लागू किया जा सकता है या बीन विधि की व्याख्या कर सकता है @PostConstruct


क्या मुझे उस पद्धति के अंदर एक ऑटोइयर्ड निर्भरता की आवश्यकता हो सकती है मैं प्रोफाइल सेट करना चाहूंगा
LppEdd

7

डेव सीर उत्तर के लिए एक उदाहरण प्रदान करना, जो एक आकर्षण की तरह काम करता है:

@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));
    }
}

7

इसे आज़माएँ और यह आपके कोड को चलाएगा जब अनुप्रयोग संदर्भ पूरी तरह से शुरू हो जाएगा।

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent arg0) {
                // EXECUTE YOUR CODE HERE 
    }
}

6

मैं वास्तव में EventListener@cahen ( https://stackoverflow.com/a/44923402/9122660 ) द्वारा एनोटेशन के उपयोग के सुझाव को पसंद करता हूं क्योंकि यह बहुत साफ है। दुर्भाग्य से मैं इसे स्प्रिंग + कोटलिन सेटअप में काम करने के लिए नहीं मिला। कोटलिन के लिए क्या काम करता है एक विधि पैरामीटर के रूप में वर्ग को जोड़ रहा है:

@EventListener 
fun doSomethingAfterStartup(event: ApplicationReadyEvent) {
    System.out.println("hello world, I have just started up");
}

वसंत बूट आवेदन वर्ग में इसे बेतरतीब ढंग से बाहर न डालें@SpringBootApplication class MyApplication { @EventListener(ApplicationReadyEvent::class) fun doSomethingAfterStartup() { println("hello world, I have just started up") } }
अहमद ना

आपको इसे @SpringBootApplication वर्ग में डालने की आवश्यकता नहीं है। कोई भी कॉन्फ़िगरेशन क्लास करेगा
जॉर्ज मारिन

5

स्प्रिंग बूट एप्लिकेशन शुरू होने के बाद कोड के ब्लॉक को निष्पादित करने का सबसे अच्छा तरीका पोस्टकोस्ट्रक्ट एनोटेशन का उपयोग कर रहा है। इसके अलावा आप उसी के लिए कमांड लाइन रनर का उपयोग कर सकते हैं।

1. PostConstruct एनोटेशन का उपयोग करना

@Configuration
public class InitialDataConfiguration {

    @PostConstruct
    public void postConstruct() {
        System.out.println("Started after Spring boot application !");
    }

}

2. कमांड लाइन रनर बीन का उपयोग करना

@Configuration
public class InitialDataConfiguration {

    @Bean
    CommandLineRunner runner() {
        return args -> {
            System.out.println("CommandLineRunner running in the UnsplashApplication class...");
        };
    }
}

3

बस वसंत बूट आवेदन के लिए CommandLineRunner लागू करें। आपको रन विधि लागू करने की आवश्यकता है,

public classs SpringBootApplication implements CommandLineRunner{

    @Override
        public void run(String... arg0) throws Exception {
        // write your logic here 

        }
}

0

सबसे अच्छा तरीका है कि आप CommandLineRunner या ApplicationRunner का उपयोग करें (रन) विधि के बीच एकमात्र अंतर है RunLineRunner स्ट्रिंग की सरणी स्वीकार करता है और ApplicationRunner ApplicationArugument को स्वीकार करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.