Come aggiungere un hook all’evento di inizializzazione del contesto dell’applicazione?

Per un Servlet regolare, immagino si possa dichiarare un listener di contesto , ma per Spring MVC Spring potrebbe renderlo più semplice?

Inoltre, se definisco un listener di contesto e quindi servlet.xml accedere ai bean definiti nel mio servlet.xml o applicationContext.xml , come potrei accedervi?

La spring ha alcuni eventi standard che puoi gestire.

Per fare ciò, è necessario creare e registrare un bean che implementa l’interfaccia ApplicationListener , qualcosa di simile a questo:

 package test.pack.age; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; public class ApplicationListenerBean implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { ApplicationContext applicationContext = ((ContextRefreshedEvent) event).getApplicationContext(); // now you can do applicationContext.getBean(...) // ... } } } 

Quindi registrare questo bean all’interno del file servlet.xml o applicationContext.xml :

  

e Spring lo notificherà quando il contesto dell’applicazione viene inizializzato.

Nella spring 3 (se si utilizza questa versione), la class ApplicationListener è generica e si può dichiarare il tipo di evento a cui si è interessati e l’evento verrà filtrato di conseguenza. Puoi semplificare un po ‘il tuo codice bean in questo modo:

 public class ApplicationListenerBean implements ApplicationListener { @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); // now you can do applicationContext.getBean(...) // ... } } 

Dalla spring 4.2 puoi usare @EventListener ( documentazione )

 @Component class MyClassWithEventListeners { @EventListener({ContextRefreshedEvent.class}) void contextRefreshedEvent() { System.out.println("a context refreshed event happened"); } } 

Crea la tua annotazione

  @Retention(RetentionPolicy.RUNTIME) public @interface AfterSpringLoadComplete { } 

Crea class

  public class PostProxyInvokerContextListener implements ApplicationListener { @Autowired ConfigurableListableBeanFactory factory; @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); String[] names = context.getBeanDefinitionNames(); for (String name : names) { try { BeanDefinition definition = factory.getBeanDefinition(name); String originalClassName = definition.getBeanClassName(); Class< ?> originalClass = Class.forName(originalClassName); Method[] methods = originalClass.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(AfterSpringLoadComplete.class)){ Object bean = context.getBean(name); Method currentMethod = bean.getClass().getMethod(method.getName(), method.getParameterTypes()); currentMethod.invoke(bean); } } } catch (Exception ignored) { } } } } 

Registra questa class annotando @Component o in xml

  

e utilizzare l’annotazione in cui si desidera utilizzare qualsiasi metodo che si desidera eseguire dopo l’inizializzazione del contesto, ad esempio:

  @AfterSpringLoadComplete public void init() {} 

Avevo un’applicazione a una sola pagina al momento dell’inserimento dell’URL che stava creando una HashMap (usata dalla mia pagina web) che conteneva dati da più database. Ho seguito le cose per caricare tutto durante l’ora di avvio del server-

1- Creatore ContextListenerClass

 public class MyAppContextListener implements ServletContextListener @Autowired private MyDataProviderBean myDataProviderBean; public MyDataProviderBean getMyDataProviderBean() { return MyDataProviderBean; } public void setMyDataProviderBean( MyDataProviderBean MyDataProviderBean) { this.myDataProviderBean = MyDataProviderBean; } @Override public void contextDestroyed(ServletContextEvent arg0) { System.out.println("ServletContextListener destroyed"); } @Override public void contextInitialized(ServletContextEvent context) { System.out.println("ServletContextListener started"); ServletContext sc = context.getServletContext(); WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(sc); MyDataProviderBean MyDataProviderBean = (MyDataProviderBean)springContext.getBean("myDataProviderBean"); Map myDataMap = MyDataProviderBean.getDataMap(); sc.setAttribute("myMap", myDataMap); } 

2- Aggiunto sotto voce in web.xml

  org.springframework.web.context.ContextLoaderListener   com.context.listener.MyAppContextListener  

3- Nella mia class Controller, codice aggiornato per il primo controllo di Map in servletContext

  @RequestMapping(value = "/index", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model) { Map myDataMap = new HashMap(); if (context != null && context.getAttribute("myMap")!=null) { myDataMap=(Map)context.getAttribute("myMap"); } else { myDataMap = myDataProviderBean.getDataMap(); } for (String key : myDataMap.keySet()) { model.addAttribute(key, myDataMap.get(key)); } return "myWebPage"; } 

Con questo grande cambiamento quando avvio il mio tomcat carica dataMap durante startTime e inserisce tutto in servletContext che viene poi utilizzato da Controller Class per ottenere risultati da servletContext già compilato.

Si prega di seguire il seguente passaggio per eseguire alcune elaborazioni dopo che il contesto dell’applicazione viene caricato, vale a dire che l’applicazione è pronta per essere pubblicata.

  1. Crea sotto annotazione vale a dire

    @Retention (RetentionPolicy.RUNTIME) @Target (valore = {ElementType.METHOD, ElementType.TYPE}) public @interface AfterApplicationReady {}

2.Create Below Class che è un listener che riceve la chiamata sullo stato di applicazione pronta.

  @Component public class PostApplicationReadyListener implements ApplicationListener { public static final Logger LOGGER = LoggerFactory.getLogger(PostApplicationReadyListener.class); public static final String MODULE = PostApplicationReadyListener.class.getSimpleName(); @Override public void onApplicationEvent(ApplicationReadyEvent event) { try { ApplicationContext context = event.getApplicationContext(); String[] beans = context.getBeanNamesForAnnotation(AfterAppStarted.class); LOGGER.info("bean found with AfterAppStarted annotation are : {}", Arrays.toString(beans)); for (String beanName : beans) { Object bean = context.getBean(beanName); Class< ?> targetClass = AopUtils.getTargetClass(bean); Method[] methods = targetClass.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(AfterAppStartedComplete.class)) { LOGGER.info("Method:[{} of Bean:{}] found with AfterAppStartedComplete Annotation.", method.getName(), beanName); Method currentMethod = bean.getClass().getMethod(method.getName(), method.getParameterTypes()); LOGGER.info("Going to invoke method:{} of bean:{}", method.getName(), beanName); currentMethod.invoke(bean); LOGGER.info("Invocation compeleted method:{} of bean:{}", method.getName(), beanName); } } } } catch (Exception e) { LOGGER.warn("Exception occured : ", e); } } } 

Infine, quando avvii la tua applicazione Spring appena prima che il log dichiarasse l’applicazione avviata, l’ascoltatore verrà chiamato.