Spring 애플리케이션에서 ApplicationContext의 사본을 정적으로 / 전역 적으로 요청하는 방법이 있습니까?
메인 클래스가 응용 프로그램 컨텍스트를 시작하고 초기화한다고 가정하면 호출 스택을 통해 클래스를 필요로하는 클래스로 전달해야합니까, 아니면 클래스가 이전에 만든 컨텍스트를 요청하는 방법이 있습니까? (내가 싱글 톤이어야한다고 가정 하는가?)
답변
컨테이너에 액세스해야하는 오브젝트가 컨테이너의 Bean 인 경우 BeanFactoryAware 또는 ApplicationContextAware 인터페이스를 구현하십시오 .
컨테이너 외부의 객체가 컨테이너에 액세스해야하는 경우 스프링 컨테이너에 표준 GoF 싱글 톤 패턴 을 사용했습니다 . 이렇게하면 응용 프로그램에 단일 톤 만 있고 나머지는 컨테이너의 단일 콩입니다.
답변
구현 ApplicationContextAware
하거나 사용할 수 있습니다 @Autowired
.
public class SpringBean {
@Autowired
private ApplicationContext appContext;
}
SpringBean
것 ApplicationContext
이 빈이 인스턴스화하는 내 주입. 예를 들어, 표준 컨텍스트 계층 구조를 갖춘 웹 애플리케이션이있는 경우 :
main application context <- (child) MVC context
그리고 SpringBean
,이 주사 메인 문맥을 갖 메인 문맥 내에서 선언되고; 그렇지 않으면 MVC 컨텍스트 내에서 선언 된 경우 MVC 컨텍스트가 주입됩니다.
답변
여기 좋은 방법이 있습니다 (원본 참조는 여기에 있습니다 :
http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
나는이 접근법을 사용했으며 잘 작동합니다. 기본적으로 응용 프로그램 컨텍스트에 대한 (정적) 참조를 보유하는 간단한 Bean입니다. 스프링 설정에서 참조하면 초기화됩니다.
원래 심판을 살펴보십시오. 매우 명확합니다.
답변
SingletonBeanFactoryLocator 사용할 수 있다고 생각합니다 . beanRefFactory.xml 파일은 실제 applicationContext를 보유하며 다음과 같이 진행됩니다.
<bean id="mainContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>../applicationContext.xml</value>
</list>
</constructor-arg>
</bean>
그리고 다음과 같은 곳에서 응용 프로그램 컨텍스트에서 Bean을 가져 오는 코드 :
BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference bf = bfl.useBeanFactory("mainContext");
SomeService someService = (SomeService) bf.getFactory().getBean("someService");
Spring 팀은이 클래스와 yadayada의 사용을 권장하지 않지만 사용 한 곳에서 나에게 적합합니다.
답변
다른 제안을 이행하기 전에 다음과 같은 질문을 해보십시오.
- 왜 ApplicationContext를 얻으려고합니까?
- ApplicationContext를 서비스 로케이터로 효과적으로 사용하고 있습니까?
- ApplicationContext에 전혀 액세스하지 않아도 되나요?
이러한 질문에 대한 답변은 특정 유형의 응용 프로그램 (예 : 웹 응용 프로그램)에서 다른 응용 프로그램보다 더 쉽지만 어쨌든 물어볼 가치가 있습니다.
ApplicationContext에 액세스하는 것은 전체 의존성 주입 원칙을 위반하지만 때로는 선택의 여지가없는 경우가 있습니다.
답변
웹 응용 프로그램을 사용하는 경우 서블릿 필터와 ThreadLocal을 사용하여 싱글 톤을 사용하지 않고 응용 프로그램 컨텍스트에 액세스하는 또 다른 방법이 있습니다. 필터에서 WebApplicationContextUtils를 사용하여 애플리케이션 컨텍스트에 액세스하고 애플리케이션 컨텍스트 또는 필요한 Bean을 TheadLocal에 저장할 수 있습니다.
주의 : ThreadLocal을 설정 해제하는 것을 잊어 버린 경우 응용 프로그램 배포를 취소 할 때 문제가 발생합니다! 따라서 마지막 부분에서 ThreadLocal을 설정 해제하는 시도를 즉시 시작하고 시작해야합니다.
물론 이것은 여전히 싱글 톤 인 ThreadLocal을 사용합니다. 그러나 실제 콩은 더 이상 필요하지 않습니다. 또한 요청 범위를 지정할 수 있으며이 솔루션은 EAR의 라이브러리가있는 애플리케이션에 여러 개의 WAR이있는 경우에도 작동합니다. 여전히 ThreadLocal의 사용은 일반 싱글 톤의 사용만큼 나쁘다고 생각할 수 있습니다. 😉
아마도 Spring은 이미 비슷한 솔루션을 제공합니까? 나는 하나를 찾지 못했지만 확실하지 않습니다.
답변
SpringApplicationContext.java
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* Wrapper to always return a reference to the Spring Application
Context from
* within non-Spring enabled beans. Unlike Spring MVC's
WebApplicationContextUtils
* we do not need a reference to the Servlet context for this. All we need is
* for this bean to be initialized during application startup.
*/
public class SpringApplicationContext implements
ApplicationContextAware {
private static ApplicationContext CONTEXT;
/**
* This method is called from within the ApplicationContext once it is
* done starting up, it will stick a reference to itself into this bean.
* @param context a reference to the ApplicationContext.
*/
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
/**
* This is about the same as context.getBean("beanName"), except it has its
* own static handle to the Spring context, so calling this method statically
* will give access to the beans by name in the Spring application context.
* As in the context.getBean("beanName") call, the caller must cast to the
* appropriate target class. If the bean does not exist, then a Runtime error
* will be thrown.
* @param beanName the name of the bean to get.
* @return an Object reference to the named bean.
*/
public static Object getBean(String beanName) {
return CONTEXT.getBean(beanName);
}
}
출처 : http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html