Есть ли способ статически / глобально запросить копию ApplicationContext в приложении Spring?
Предполагая, что основной класс запускается и инициализирует контекст приложения, нужно ли передавать его через стек вызовов любым классам, которые в этом нуждаются, или есть ли у класса способ запросить ранее созданный контекст? (Который, я полагаю, должен быть синглтоном?)
источник
instance()
как фабрику. Однако, я думаю, что я просто позволил всему коду вне контейнера сначала обращаться к контейнеру. Затем этот код может запрашивать объекты из контейнера.Вы можете реализовать
ApplicationContextAware
или просто использовать@Autowired
:SpringBean
будетApplicationContext
введен, в рамках которого создается этот боб. Например, если у вас есть веб-приложение с довольно стандартной иерархией контекстов:и
SpringBean
объявляется в основном контексте, в него вводится основной контекст; в противном случае, если он объявлен в контексте MVC, в него будет вставлен контекст MVC.источник
@Inject
тожеВот хороший способ (не мой, оригинальная ссылка здесь: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
Я использовал этот подход, и он отлично работает. По сути, это простой компонент, содержащий (статическую) ссылку на контекст приложения. Ссылка на него в весеннем конфиге инициализируется.
Посмотрите на оригинальную ссылку, это очень ясно.
источник
getBean
из кода, который выполняется во время модульного теста, поскольку контекст Spring не будет настроен до того, как вы его попросите. Это состояние гонки, в которое я попал сегодня после двух лет успешного использования этого подхода.Я считаю, что вы могли бы использовать SingletonBeanFactoryLocator . Файл beanRefFactory.xml будет содержать фактический applicationContext, он будет выглядеть примерно так:
И код для получения bean-компонента из контекста приложения от whereever будет выглядеть примерно так:
Команда Spring не рекомендует использовать этот класс и yadayada, но там, где я его использовал, он мне очень понравился.
источник
Прежде чем реализовать какие-либо другие предложения, задайте себе эти вопросы ...
Ответы на эти вопросы проще в некоторых типах приложений (например, в веб-приложениях), чем в других, но в любом случае их стоит спросить.
Доступ к ApplicationContext нарушает принцип внедрения зависимостей, но иногда у вас нет большого выбора.
источник
Если вы используете веб-приложение, существует также другой способ доступа к контексту приложения без использования синглетонов с помощью сервлет-фильтра и ThreadLocal. В фильтре вы можете получить доступ к контексту приложения с помощью WebApplicationContextUtils и сохранить либо контекст приложения, либо необходимые компоненты в TheadLocal.
Внимание: если вы забудете сбросить ThreadLocal, у вас будут неприятные проблемы при попытке удалить приложение! Таким образом, вы должны установить его и немедленно начать попытку, которая удаляет ThreadLocal в finally-части.
Конечно, это все еще использует синглтон: ThreadLocal. Но настоящие бобы не должны быть больше. Можно даже определить область запроса, и это решение также работает, если у вас есть несколько WAR-файлов в приложении с библиотеками в EAR. Тем не менее, вы можете считать это использование ThreadLocal таким же плохим, как и использование простых синглетонов. ;-)
Возможно, Spring уже предлагает подобное решение? Я не нашел ни одного, но точно не знаю.
источник
Источник: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
источник
Взгляните на ContextSingletonBeanFactoryLocator . Он предоставляет статические средства доступа для получения контекста Spring, предполагая, что они были зарегистрированы определенным образом.
Это не красиво, и сложнее, чем, возможно, вы хотели бы, но это работает.
источник
Существует множество способов получить контекст приложения в приложении Spring. Те приведены ниже:
Через ApplicationContextAware :
Здесь
setApplicationContext(ApplicationContext applicationContext)
методом вы получите приложениеContextЧерез Autowired :
Здесь
@Autowired
ключевое слово предоставит applicationContext. Autowired имеет некоторые проблемы. Это создаст проблему при юнит-тестировании.источник
Обратите внимание, что, сохраняя любое состояние из текущего
ApplicationContext
или самогоApplicationContext
себя в статической переменной - например, с помощью одноэлементного шаблона - вы сделаете свои тесты нестабильными и непредсказуемыми, если вы используете Spring-test. Это связано с тем, что Spring-test кэширует и повторно использует контексты приложения в той же JVM. Например:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Когда выполняется тест A, создается an
ApplicationContext
, и любые компоненты bean, реализующиеApplicationContextAware
или выполняющие автоматическую разводку,ApplicationContext
могут записывать в статическую переменную.Когда выполняется тест B, происходит то же самое, и статическая переменная теперь указывает на тест B
ApplicationContext
Когда выполняется тест C, бины не создаются, поскольку
TestContext
(и в данном случаеApplicationContext
) из теста A используется повторно. Теперь у вас есть статическая переменная, указывающая на другую,ApplicationContext
отличную от той, которая в данный момент содержит компоненты для вашего теста.источник
Не уверен, насколько это будет полезно, но вы также можете получить контекст при инициализации приложения. Это самое раннее, что вы можете получить контекст, даже до
@Autowire
.источник
Пожалуйста, обратите внимание, что; код ниже создаст новый контекст приложения вместо использования уже загруженного.
Также обратите внимание, что это
beans.xml
должно быть частьюsrc/main/resources
средств в войне, в которые оноWEB_INF/classes
будет загружено, какapplicationContext.xml
указано вWeb.xml
.Это трудно упомянуть
applicationContext.xml
путь вClassPathXmlApplicationContext
конструкторе.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
не сможет найти файл.Поэтому лучше использовать существующий applicationContext с помощью аннотаций.
источник
Я знаю, что на этот вопрос дан ответ, но я хотел бы поделиться кодом Kotlin, который я сделал, чтобы получить контекст Spring.
Я не специалист, поэтому я открыт для критиков, отзывов и советов:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Теперь весенний контекст общедоступен и может вызывать тот же метод, не зависящий от контекста (тесты junit, bean-компоненты, созданные вручную классы), как в этом Java-сервлете:
источник
Выполните autowire в Spring bean, как показано ниже: @Autowired private ApplicationContext appContext;
у вас будет объект applicationcontext.
источник
Подход 1. Вы можете внедрить ApplicationContext, реализовав интерфейс ApplicationContextAware. Ссылочная ссылка .
Подход 2: Контекст приложения Autowire в любом из управляемых bean-компонентов.
Ссылочная ссылка .
источник