2011-12-31 23 views
52

Đối với một Servlet thông thường, tôi đoán bạn có thể khai báo một số context listener, nhưng đối với Spring MVC Spring có làm cho việc này dễ dàng hơn không?Cách thêm móc vào sự kiện khởi tạo ngữ cảnh ứng dụng?

Hơn nữa, nếu tôi xác định trình nghe ngữ cảnh và sau đó sẽ cần truy cập vào các hạt được xác định trong số servlet.xml hoặc applicationContext.xml của tôi, làm cách nào tôi có quyền truy cập vào chúng?

Trả lời

82

Spring has some standard events which you can handle.

Để làm điều đó, bạn phải tạo và đăng ký một bean mà thực hiện giao diện ApplicationListener, một cái gì đó như thế này:

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

Sau đó bạn đăng ký đậu này trong vòng của bạn tập tin servlet.xml hoặc applicationContext.xml:

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

và Spring sẽ thông báo khi ngữ cảnh ứng dụng được khởi tạo.

Vào mùa xuân 3 (nếu bạn đang sử dụng phiên bản này), ApplicationListener class is generic và bạn có thể khai báo loại sự kiện mà bạn quan tâm và sự kiện sẽ được lọc tương ứng. Bạn có thể đơn giản hóa một chút đang đậu của bạn như thế này:

public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> { 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 
     ApplicationContext applicationContext = event.getApplicationContext(); 
     // now you can do applicationContext.getBean(...) 
     // ... 
    } 
} 
+0

ok, cảm ơn.bạn nên biết rằng spring3 lọc các sự kiện. Tôi đã chú ý đến lớp ứng dụng trước đây. nhưng các móc của nó cũng sẽ được gọi cho RequestHandledEvent. –

+0

Bất kỳ ý tưởng gì sẽ xảy ra nếu bạn sử dụng các công cụ chú thích và bạn khai báo hai lớp? Không chú thích (XML) và hai? Họ sẽ bắn theo thứ tự tuyên bố? thanks;) – momomo

+0

Chỉ để biết thông tin, sự kiện cho bối cảnh bắt đầu là ContextStartedEvent Tài liệu: - http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/context/event/ContextStartedEvent. html –

58

Kể từ mùa xuân 4.2 bạn có thể sử dụng @EventListener (documentation)

@Component 
class MyClassWithEventListeners { 

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

làm cách nào để in các thuộc tính, vv, phương pháp này dường như không có tham số? –

1

Tôi đã có một ứng dụng trang duy nhất trên nhập URL nó đã tạo ra một HashMap (được trang web của tôi sử dụng) chứa dữ liệu từ nhiều cơ sở dữ liệu. tôi đã điều sau đây để tải tất cả mọi thứ trong máy chủ bắt đầu tốn nhiều thời gian

1- Tạo 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- Thêm bên dưới mục trong web.xml

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

3- Trong điều khiển Lớp của tôi đã cập nhật mã để kiểm tra Bản đồ đầu tiên trong 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"; 

     } 

Với sự thay đổi này nhiều khi tôi bắt đầu tomcat của tôi nó tải dataMap trong startTime và đặt mọi thứ trong servletContext mà sau đó được sử dụng bởi Controller Class để có được kết quả từ servletContext đã được điền sẵn.

1

Tạo chú thích của mình

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

Tạo lớp

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

Đăng ký lớp này bằng cách @Component chú thích hoặc trong xml

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

và sử dụng chú thích nơi bạn wan trên phương pháp nào đó bạn muốn chạy sau khi bối cảnh được khởi tạo, như:

@AfterSpringLoadComplete 
    public void init() {} 
Các vấn đề liên quan