2013-10-04 6 views
1

같은 JSF 요청을 위해 내 PhaseListener의 beforePhase()와 afterPhase() 메소드 사이에서 속성을 공유해야합니다.PhaseListener의 beforePhase() 및 afterPhase() 메서드간에 스레드를 안전하게 안전하게 공유하려면 어떻게해야합니까?

다음 코드 조각은 스레드로부터 안전한가요?

public class MyPhaseListener implements PhaseListener { 

    private MyObject o = null; 

    @Override 
    public void beforePhase(PhaseEvent event) { 
    if (condition) { 
     o = new MyObject(); 
    } 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
    if (o != null) { 
     o.process(); 
     o = null; 
    } 
    } 

    @Override 
    public PhaseId getPhaseId() { 
    return PhaseId.RESTORE_VIEW; 
    } 

} 

그렇지 않은 경우 다른 해결책은 무엇입니까?

답변

3

, 조정 예를 Object로 업데이트되었다 보았다. 여러 요청에서 공유되는 하나의 위상 수신기 인스턴스 만 applicationwide가 있습니다. 기본적으로 위상 수신기는 @ApplicationScoped 관리 빈과 같습니다.

그냥 컨텍스트 속성으로 설정하십시오.

public class MyPhaseListener implements PhaseListener { 

    @Override 
    public void beforePhase(PhaseEvent event) { 
    if (condition) { 
     event.getFacesContext().setAttribute("o", new MyObject()); 
    } 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
    MyObject o = (MyObject) event.getFacesContext().getAttribute("o"); 
    if (o != null) { 
     o.process(); 
    } 
    } 

    @Override 
    public PhaseId getPhaseId() { 
    return PhaseId.RESTORE_VIEW; 
    } 

} 
0

이 경우 ThreadLocal을 사용할 수 있지만 다른 클래스 로더가있는 환경에서는 메모리 누수가 발생하는 경향이 있습니다.. 처리가 beforePhase()afterPhase() 방법 사이 (... 예를 들어 예외) 중단 될 수있는 경우에 당신이 있는지 확인해야한다, 또한

... 주어진 환경에서이 있는지 확인하십시오의 ThreadLocal는 처리해야 ...

public class MyPhaseListener implements PhaseListener { 

    //if null is a valid value, no initial setting is needed 
    private ThreadLocal<Object> myStateObject = new ThreadLocal<Object>(); 

    @Override 
    public void beforePhase(PhaseEvent event) { 

    //might be needed, to guarrantee no residue from an aborted processing is in there 
    myState.set(null); 
    if (condition) { 
     myState.set(<Object representing the state>); 
    } 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
    try { 
     Object stateObject = myState.get(); 
     if (stateObejct!=null) { 
      //do what you have to 
     } 
    } finally { 
     //to be sure 
     myState.remove(); 
    } 
    } 
} 

this article에서 저자도의 ThreadLocal을 사용 또한

,: 적절하게 ...

는 것처럼 보일 것이다 것입니다 변경 가능한 인스턴스 레벨 정보를 공유 할 수없는 이유를 설명:하지만 기억해야 할

한 가지는, 그 PhaseListener 인스턴스 자체가 응용 프로그램 전체 싱글 인 JSF 라이프 사이클에 의해 참조되는 응용 프로그램 전체 싱글 톤입니다 . 편집

은 부울이 확실히 스레드 안전하지 않습니다

+0

'ThreadLocal' 변수를 코드의 다른 곳에서 필요로하지 않는 한 낭비하지 마십시오. – BalusC