How to add a binding to an application context initialization event?

For a regular servlet, I think you could declare a context listener , but is it easier for Spring MVC Spring?

Also, if I define a context listener and then have to access the beans defined in my servlet.xml or applicationContext.xml , how can I access them?

+49
spring model-view-controller applicationcontext
Dec 31 '11 at 5:30
source share
4 answers

Spring has several standard events that you can handle.

To do this, you must create and register a bean that implements the ApplicationListener interface, something like this:

 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(...) // ... } } } 

Then you register this bean in servlet.xml or applicationContext.xml :

 <bean id="eventListenerBean" class="test.pack.age.ApplicationListenerBean" /> 

and Spring report this when initializing the application context.

In Spring 3 (if you are using this version), the ApplicationListener class is generic , and you can declare the type of event that interests you, and the event will be filtered accordingly. You can simplify your bean code a bit as follows:

 public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext applicationContext = event.getApplicationContext(); // now you can do applicationContext.getBean(...) // ... } } 
+82
Dec 31 '11 at 10:46
source share

Since Spring 4.2, you can use @EventListener ( documentation )

 @Component class MyClassWithEventListeners { @EventListener({ContextRefreshedEvent.class}) void contextRefreshedEvent() { System.out.println("a context refreshed event happened"); } } 
+53
Oct 27 '15 at 2:08
source share

Create your annotation

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

Create class

  public class PostProxyInvokerContextListener implements ApplicationListener<ContextRefreshedEvent> { @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) { } } } } 

Register this class with @Component annotation or in xml

 <bean class="ua.adeptius.PostProxyInvokerContextListener"/> 

and use annotation where you want to use any method you want to run after context initialization, for example:

  @AfterSpringLoadComplete public void init() {} 
+1
Aug 03 '17 at 17:36 on
source share

I had a one-page application when entering a URL in which it created a HashMap (used by my web page) that contained data from several databases. I followed these steps to load everything during server startup -

1- Created by 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<String, Object> myDataMap = MyDataProviderBean.getDataMap(); sc.setAttribute("myMap", myDataMap); } 

2- Added entry below in web.xml

 <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>com.context.listener.MyAppContextListener</listener-class> </listener> 

3- In my controller class, the code for the first card check in servletContext has been updated

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

With this big change, when I start my tomcat, it loads the dataMap during startTime and puts everything in the servletContext, which is then used by the Controller class to get the results from the already filled servletContext.

0
Apr 20 '16 at 11:03
source share



All Articles