如何将钩子添加到应用程序上下文初始化事件?

对于一个常规的Servlet,我想你可以声明一个上下文监听器 ,但是对于Spring MVC,Spring会让这个更简单吗?

此外,如果我定义一个上下文监听器,然后需要访问在我的servlet.xmlapplicationContext.xml定义的bean,我将如何访问它们?

Spring有一些你可以处理的标准事件。

为此,您必须创build并注册一个实现ApplicationListener接口的bean,如下所示:

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

然后在servlet.xmlapplicationContext.xml文件中注册这个bean:

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

Spring会在应用上下文初始化时通知它。

在Spring 3中(如果您使用的是此版本), ApplicationListener类是通用的 ,您可以声明您感兴趣的事件types,并相应地过滤该事件。 你可以像这样简化一下你的bean代码:

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

从Spring 4.2开始,你可以使用@EventListener ( documentation )

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

创build您的注释

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

创build课堂

  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) { } } } } 

通过@Component注解或xml注册这个类

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

并且在上下文初始化之后使用任何想要运行的方法使用注释,如:

  @AfterSpringLoadComplete public void init() {} 

我有一个单一的页面应用程序inputURL它创build一个HashMap(由我的网页使用),其中包含来自多个数据库的数据。 我在服务器启动的时候,

1-创buildContextListenerClass

 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-在web.xml中添加以下条目

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

3-在我的控制器类更新代码首先检查在servletContext地图

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

有了这个变化,当我启动我的tomcat时,它会在startTime中加载dataMap,并将所有内容放在servletContext中,然后由Controller Class使用它从已填充的servletContext中获取结果。