Как связать события контекста приложения Spring с другим контекстом - PullRequest
16 голосов
/ 16 декабря 2011

У меня есть веб-приложение Spring с двумя контекстами: одно (applicationContext) построено на ContextLoaderListener, а второе (webContext) построено на DispatcherServlet.

Внутри applicationContext находится компонент (org.springframework.security.authentication.DefaultAuthenticationEventPublisher), который запускает контекстные события весны.

Но получатель для события определен в webContext. И этот получатель не получил событие. (Если поставить приемник для проверки в applicationContext, тогда он получит событие, но я не могу этого сделать, потому что мне нужны webContext s для его функциональности.)

Итак, мой вопрос: как соединить события от applicationContext до webContext?

Ответы [ 5 ]

9 голосов
/ 15 февраля 2015

У меня была та же проблема, я решил ее, переместив компоненты, создающие событие, в веб-контекст. Однако вы можете решить свою проблему, вручную подключив прослушиватель событий, что-то вроде этого (этот код не скомпилирован, поэтому он не проверен):

@Component    
public class BeanInWebContext implements ApplicationListener<SomeEvent> {

    @Autowired
    private ApplicationContext webContext;

    @PostConstruct
    public void registerAsListener() {
        // get parent context
        AbstractApplicationContext appContext = (AbstractApplicationContext) webContext.getParent();
        // register self as a listener, this method is in AbstractApplicationContext
        appContext.addApplicationListener(this);
    }

    @Override
    public void onApplicationEvent(SomeEvent event) {
    }

}
4 голосов
/ 12 февраля 2015

Я думаю, что реальный ответ заключается в том, что вы можете настроить свое приложение по-другому (чтобы у вас был только один контекст) Я думаю, что в вашем web.xml вам нужно сделать что-то вроде этого:

<servlet>
    <servlet-name>example</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>               
            classpath:/META-INF/applicationSpringConfig.xml
        </param-value>
    </init-param> 
</servlet>

Но чтобы ответить на более глубокий вопрос. Кто-то еще указывает, что вы можете использовать include в вашем файле Spring (в самом деле, в приведенном выше примере в вашем сервлете диспетчера может быть указано более одного параметра Springconfig). Но когда вы включаете другие файлы контекста, вы не разделяете экземпляры bean-компонентов, а только определения.

Модульные приложения Spring были единственным реальным недостатком Spring по сравнению с EJB и т. Д., Которые привели Spring к использованию OSGi. И ответ на основной вопрос о том, как разделить контекст Spring, официально вы делитесь экземплярами Spring Bean между контекстами, используя OSGi (spring dm)

3 голосов
/ 04 августа 2014

Как указано в документации для платформы Spring, простой механизм ApplicationEvent предназначен только для использования в одном и том же контексте приложения, я не знаю, что возможно распространять события в дочерние контексты.

Если вам нужно более продвинутое решение, вы можете использовать более совершенное решение, такое как Java Message Service или Spring Integration.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-functionality-events

3 голосов
/ 17 декабря 2011

Попробуйте переместить издателя событий в файл веб-контекста, где он должен иметь видимость по всему контексту приложения.Аналогичная проблема возникает при настройке безопасности метода в контексте родительского приложения .Контекст родительского приложения (загруженный ContextLoaderListener) не знает о дочернем (веб) контексте.

Вы также можете использовать один контекст приложения для всего приложения, если вам действительно не нужен родитель-детские отношения между двумя.Часто это только мешает, и легче, если все компоненты определены в одном и том же пространстве.

0 голосов
/ 12 ноября 2014

Мы можем использовать тег import, чтобы импортировать / соединить 2 различных контекста, созданных таким образом, чтобы видимость событий / компонентов была доступна и доступна для совместного использования.

<import resource="applicationContext_name.xml"/>

В этом импорте контекстный XML, который настроен для создания из ContextLoaderListener в контекстном XML DispatcherServlet.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...