Загрузка иерархии ApplicationContexts в WebApplicationInitializer

Я использую Servlet 3 (Tomcat 7) + Spring 3.1 и пытаюсь загрузить свое веб-приложение с помощью WebApplicationInitializer.

В обычных примерах, которые я видел, у вас есть корневой ApplicationContext, загруженный с помощью ContextLoaderListener, и сервлет ApplicationContext, загруженный с помощью DispatcherServlet.

(Чтобы было ясно, я говорю не о web.xml, а о программном обеспечении внутри WebApplicationInitializer).

Теперь я хотел бы иметь иерархию ApplicationContexts, скажем:

Корень -> AppContext1 -> AppContext2 -> ServletAppContext

-> обозначает отношение Родитель -> Дочерний элемент. Каждый AppContext может получить доступ к своим собственным компонентам и компонентам своих предков.

Например:

  • Корень определяет свойства, DAO и TX.
  • AppContext1 определяет репозитории JPA и Spring Data.
  • AppContext2 определяет каналы интеграции JMS и Spring.
  • ServletAppContext определяет контроллеры и представления.

Мой первый подход состоял в том, чтобы добавить корневой ApplicationContext в ContextLoaderListener, а затем установить его в качестве родителя AppContext1. Установите AppContext1 в качестве родителя AppContext2. Установите AppContext2 в качестве родителя ServletAppContext. И, наконец, свяжите ServletAppContext с DispatcherServlet.

Дело в том, что во время выключения DispatcherServlet закрывает ServletAppContext, но не распространяется. AppContext1 и AppContext2 никогда не закрываются, их bean-компоненты никогда не освобождаются. Поэтому я предполагаю, что использую неправильный подход.

Я попытался связать AppContext2 с ContextLoaderListener вместо Root. В этом случае AppContext2 закрывается, но AppContext1 и Root остаются открытыми.

Я также не могу иметь 3 ContextLoaderListeners, по 1 для каждого из моих AppContexts (Root, 1, 2).

У меня вопрос, какой правильный подход в этой ситуации? Я открыт для предложений.


person Luciano    schedule 20.10.2012    source источник
comment
Просто из любопытства, зачем вообще нужна такая сложная схема.   -  person gkamal    schedule 20.10.2012
comment
Идея состоит в том, чтобы добиться лучшей модульности bean-компонентов (что, я думаю, должно быть хорошей практикой). Я не думаю, что это должно быть сложно, и, конечно, вы не можете сделать это с помощью web.xml, так что это новый подход. В качестве бонуса он сводит к минимуму количество bean-компонентов, которые не подходят для постобработки.   -  person Luciano    schedule 20.10.2012


Ответы (2)


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

Если это линейное отношение (т. е. для каждого контекста существует только один дочерний элемент), то вы можете использовать расширенную реализацию ApplicationContext, метод close которой также вызывает родительское закрытие.

Если это не линейное отношение, то вы можете реализовать механизм подсчета ссылок, чтобы отслеживать количество активных дочерних контекстов, когда он достигает 0, закрывая контекст.

Прежде чем делать что-либо из этого, вы должны серьезно пересмотреть причину наличия такого большого количества контекстов. Возможно, было бы лучше создать только два контекста и использовать импорт для подключения файлов конфигурации. Я выгляжу как излишняя инженерия для меня. Я не могу придумать хороший вариант использования чего-то подобного, было бы очень интересно услышать, почему вы это делаете.

person gkamal    schedule 20.10.2012
comment
Смотрите мой комментарий выше для объяснения - person Luciano; 20.10.2012

Итак, ясно, что я пытаюсь сделать что-то, к чему Spring (по крайней мере, до версии 3.1) не готов.

person Luciano    schedule 21.11.2012