Подтвердить что ты не робот

Как добавить привязку к событию инициализации контекста приложения?

Для обычного сервлета, я думаю, вы могли бы объявить прослушиватель контекста, но для Spring MVC Spring сделать это проще?

Кроме того, если я определяю прослушиватель контекста, а затем должен получить доступ к beans, определенному в моих servlet.xml или applicationContext.xml, как я могу получить к ним доступ?

4b9b3361

Ответ 1

Spring имеет несколько стандартных событий, которые вы можете обрабатывать.

Чтобы сделать это, вы должны создать и зарегистрировать bean, который реализует интерфейс ApplicationListener, примерно так:

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

Затем вы регистрируете этот bean в файле servlet.xml или applicationContext.xml:

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

и Spring сообщают об этом при инициализации контекста приложения.

В Spring 3 (если вы используете эту версию) класс ApplicationListener является общим, и вы можете объявить тип события, который вас интересует, и событие будет соответствующим образом отфильтровано. Вы можете немного упростить свой код bean следующим образом:

public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {

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

Ответ 2

Так как Spring 4.2, вы можете использовать @EventListener (документация)

@Component
class MyClassWithEventListeners {

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

Ответ 3

Создайте свою аннотацию

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

Создать класс

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

Ответ 4

У меня было одностраничное приложение при вводе URL-адреса, в котором он создавал HashMap (используемый моей веб-страницей), который содержал данные из нескольких баз данных. Я выполнил следующие действия, чтобы загрузить все во время запуска сервера -

1- Создан 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- Добавлена ​​запись ниже в 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, он загружает dataMap во время startTime и помещает все в servletContext, который затем используется классом Controller для получения результатов из уже заполненного servletContext.