2010-07-02 2 views
9

У меня есть Spring ApplicationContext, где я объявляю сервер сервера Jetty и запускаю его. Внутри Jetty у меня есть DispatcherServlet и несколько контроллеров. Как заставить DispatcherServlet и его контроллеры использовать bean-компоненты из того же ApplicationContext, где объявлен Jetty?Как встраивать Jetty в Spring и использовать его в том же AppContext, в который он был встроен?

Фактически, в этом внешнем контексте у меня есть пара подобных демонам и их зависимости. Контроллеры внутри Jetty используют одни и те же зависимости, поэтому я бы хотел избежать дублирования их внутри и снаружи Jetty.

ответ

5

Я сделал это некоторое время назад.

Spring documentation предлагает использовать ContextLoaderListener для загрузки контекста приложения для сервлетов. Вместо этого класса Spring используйте свой собственный слушатель. Главное здесь, что ваш пользовательский прослушиватель может быть определен в конфигурации Spring и может знать о контексте приложения, в котором он определен; поэтому вместо загрузки нового контекста приложения он просто возвращает этот контекст.

Слушатель будет выглядеть примерно так:

public class CustomContextLoaderListener extends ContextLoaderListener implements BeanFactoryAware { 

    @Override 
    protected ContextLoader createContextLoader() { 
     return new DelegatingContextLoader(beanFactory); 
    } 

    protected BeanFactory beanFactory; 

    @Override 
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 
     this.beanFactory = beanFactory; 
    } 

} 

и DelegatingContextLoader делает это:

public class DelegatingContextLoader extends ContextLoader { 

    protected BeanFactory beanFactory; 

    public DelegatingContextLoader(BeanFactory beanFactory) { 
     this.beanFactory = beanFactory; 
    } 

    @Override 
    protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent) throws BeansException { 
     return new GenericWebApplicationContext((DefaultListableBeanFactory) beanFactory); 
    } 

} 

Это немного грязный, и, вероятно, может быть улучшен, но это сделал работу за меня.

+1

Спасибо! После некоторых изменений я решил свою проблему. С этим решением я получил исключение 'ApplicationEventMulticaster not initialized', потому что этот' GWAC' не был обновлен, но когда я вызывал 'refresh()' на нем, у меня было исключение, что постпроцессоры называются второй раз. Поэтому вместо использования 'GWAC' я создал класс' WrapperWebApplicationContext', который делегировал все вызовы 'ApplicationContext', переданные в конструкторе. Теперь он работает отлично. Кроме того, я переопределил 'createWebApplicationContext'' ContextLoaderListener' - таким образом, нет необходимости использовать класс ContextLoader. – Fixpoint

+0

Хорошо. Я в тупике. Как вы получаете контейнер сервлета для использования компонента Listener, который вы определили в конфигурации Spring, вместо создания нового экземпляра, который ничего не знает о applicationContext/beanFactory? – CupawnTae