2014-10-31 2 views
1

나는 특정 서비스를 주입하는 컨트롤러와 필터를 가지고 있습니다. 해당 서비스에서 특정 정보를 저장하려고하는 해시 맵이 있습니다. 내가 겪고있는 문제는 해당 서비스의 단일 인스턴스가 만들어져 내 컨트롤러와 필터에 주입되어지도의 두 인스턴스가있는 것처럼 보입니다. 왜 그랬는지 나는 상실했다. 아무리 맵을 인스턴스화 (또는 삽입)해도 동작은 동일합니다.스프링 싱글 톤 @ 자동 전화 서비스 및 공유 상태

서비스의 두 인스턴스가 생성되어 컨트롤러와 필터에 각각 하나씩 삽입되어 주입된다는 점이 밝혀졌습니다. 왜 이런 일이 일어나고 어떻게 해결해야하는지 명확하지 않습니다.

는 다음 코드의 추출물 : 여기

@Controller 
public MyController { 



    @Autowired 
    private MyService myService; 


    someEndpoint() { 
    .... 
    myService.putData(key, value); 
    ..... 
    } 


} 


public class MyFilter extends GenericFilterBean { 


    @Autowired 
    private MyService myService; 


    public void doFilter(...) { 

    //this is where I have a problem. 
    // the reference myService.myMap seems to be pointing to a different instance 
    // than the service.myMap in the controller which doesn't make any sense to me 
    // the filter obviously intercepts all requests so I would expect that after that particular 
    // endpoint is accessed the data will be there for subsequent requests 
    myService.getData(..); 

    } 

    ..... 
} 


@Service 
public class MyService { 


    private Map <String,String> myMap = new HashMap <String,String>(); 


    public String getData(String key) { 
    return myMap.get(key); 
    } 

    public void putData(String key, String value){ 
    myMap.put(key,value); 
    } 


} 

이 앱 config.xml에

<?xml version="1.0" encoding="utf-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
          http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd"> 

    <context:component-scan base-package="com.mycompany.myPackage"/> 
    <context:annotation-config /> 


    ....... 

    <security:http 
    ........ 
    ........ 
    <security:custom-filter ref="myFilter" position="FORM_LOGIN_FILTER" /> 
    .... 


    ........... 

    <bean class="com.mycompany.filters.MyFilter" id="myFilter"/> 

과의 web.xml의 추출물

<context-param> 
 
     <param-name>contextConfigLocation</param-name> 
 
     <param-value>/WEB-INF/app-config.xml</param-value> 
 
    </context-param> 
 
    <listener> 
 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
 
    </listener> 
 

 

 
    <servlet> 
 
     <servlet-name>Dispatcher Servlet</servlet-name> 
 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
 
     <init-param> 
 
      <param-name>contextConfigLocation</param-name> 
 
      <param-value>/WEB-INF/app-config.xml</param-value> 
 
     </init-param> 
 
     <load-on-startup>1</load-on-startup> 
 
    </servlet> 
 

 

 
    <servlet-mapping> 
 
     <servlet-name>Dispatcher Servlet</servlet-name> 
 
     <url-pattern>/webservice/*</url-pattern> 
 
    </servlet-mapping> 
 

 
<filter> 
 
    <filter-name>springSecurityFilterChain</filter-name> 
 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
 
</filter> 
 
<filter-mapping> 
 
    <filter-name>springSecurityFilterChain</filter-name> 
 
    <url-pattern>/*</url-pattern> 
 
</filter-mapping>

도움을 주시면 대단히 감사하겠습니다.

+0

몇 개의 컨텍스트가 있습니까? web.xml을 게시 할 수 있습니까? 또한 문맥 구성? – grid

답변

0

GenericFilterBean이 응용 프로그램 컨텍스트에 없습니다. 위의 코드에서 java.lang.InstantiationException을 예상합니다. bean의 필터는 ServletContext을 통해 얻을 수 있습니다. 다른 인스턴스 생성 트릭은 맵 중복을 초래합니다.

+0

"GenericFilter가 응용 프로그램 컨텍스트에 있지 않다"는 의미를 상세하게 설명해 주실 수 있습니까? 내 응용 프로그램 컨텍스트에서 MyFilter를 정의하면 인스턴스화 예외가 발생하지 않습니다 ... –

+0

그래서 두 개의 다른 컨텍스트가 있음을 의미합니다. 그래서 두 가지 경우가 있습니다. 귀하의 코드에서 서비스와 컨트롤러는 주석을 달았지만 필터는 그렇지 않습니다. ** GenericFilter **에 대한 아이디어로는 응용 프로그램 컨텍스트에 있지 않아야합니다. – Dmytro

+0

그렇다면 두 가지 컨텍스트가 왜/어떻게 생성됩니까? 내 app-config (위의 편집 참조)에서 필터를 정의하기 때문에 필터에 주석을 추가하지 않았습니다. 거기에 다른 요소에 의해 참조되기 때문에 응용 프로그램 컨텍스트에서 정의해야했습니다. –

0

MyService 클래스 인스턴스가 하나만 생성되었는지 확인하십시오. 이를 확인하는 가장 간단한 방법은 기본 생성자 구현을 제공하고 그 안에 일부 텍스트를 인쇄하는 것입니다. 내가 약간의 의혹을 가지고 있기 때문에 이것을 확인하고 알려주세요. 이것이 사실이고,이면 MyService 클래스의 두 인스턴스가있는 경우

, 가능성은 매핑 일부 데이터를 넣을 때, 당신이이면 MyService의 예 A를 사용하고 맵에서 데이터를 얻을 때 인스턴스를 사용하는 것이있다 B MyService ... 나는이 생각을 계속하거나 그만두기를 당신의 응답을 기다릴 것이다. 당신의 web.xml에

+0

그건 내 첫번째 생각 이었지만 위의 질문에서 언급 한 것처럼 MyService의 동일한 인스턴스가 주입됩니다. 문제의 원인이 아닙니다. –

1

당신은 설정 :

서블릿에 의해 시작 하나 개의 웹 애플리케이션 컨텍스트를 생성
<servlet> 
    <servlet-name>Dispatcher Servlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/app-config.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

.

그런 다음 당신은 또한이 : 또한 귀하의 경우 중복 하나, 부모 루트 웹 애플리케이션 컨텍스트를 생성

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/app-config.xml</param-value> 
</context-param> 

합니다. 이 스킴은 적절하게 사용되는 서블릿이 더 많을 수있는 경우를 선호한다. 각 서블릿은 각각의 고립 된 컨텍스트를 정의하지만 공통 루트 컨텍스트 (서비스, 데이터 소스 등)에서 Bean 정의를 상속한다. 또한 계층화 된 컨텍스트를 만드는 데 유용한 로드맵을 제공합니다. 즉, 서비스 bean이 사용자의 mvc 계층에 종속되지 않도록합니다.

<servlet> 
    <servlet-name>Dispatcher Servlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value></param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

것은주의 : 둘 이상의 구성 파일이 없다면

, 당신은 당신의 서블릿 구성의는 contextConfigLocation에 빈 값을 할당해야합니다. 매개 변수를 생략하지 마십시오. Spring은 서블릿을 기반으로하는 기본 설정 파일 이름을 유추하며 존재하지 않으면 불평 할 것이다.

+0

감사합니다. 귀하의 의견은 올바른 방향으로 나를 지적했습니다. 내 컨트롤러의 매핑을 깨뜨릴 수 있으므로 위의 제안에 따라 문제를 해결할 수 없으므로 대신 DispatcherServlet에 하나씩 전달하는 두 개의 개별 구성 파일을 만들었습니다. –