2017-12-29 12 views
0

는 여기이 클래스 자,이 요청이있을 때 (당신이 기본 범위를 사용하는 경우) 생성 및 사용 단지 빈입니다 JSF의 ManagedBean은,에 의해 사용되는내가 작성한 클래스는 스레드 안전성 측면에서 깨졌습니까? ManagedBeans는 다른 쓰레드에서 사용 되는가?

@Component 
public class LoginDao { 
    @Autowired 
    private JdbcTemplate jdbcTemplate; 

    public List<Map<String, Object>> getUser(final String username, final String password) { 
     return jdbcTemplate.queryForList("select * from users where username=? and password=?", new Object[]{username, password}); 
    } 
} 

을 썼다.

@ManagedBean 
public class Login implements Serializable { 
    @ManagedProperty("#{loginDao}") 
    private LoginDao loginDao; 
//..do something with loginDao 
} 

나는이 완전히 때문에 파괴되는 것을 무서워 무엇을 JSF에 의해 생성 된 로그인 콩 사용 갈 때 만약 그 loginDao의 필드 JdbcTemplate을가 null로 볼 삽입 된 객체이며, loginDao?

웹 서버가 해당 요청을 처리하기 위해 별도의 스레드를 사용하고 LoginDao의 jdbcTemplate 필드가 final이 아니고 이전에 생성자에 설정되어 있기 때문에 Login Bean이 요청을 처리하는 데 사용되면 별도의 스레드에서 실행됩니다 Login bean의 실행은 jdbcTemplate을 Login 인스턴스에서 null로 볼 수 없습니까? 이 문제를 해결하여 jdbcTemplate을 휘발성으로 만드는 방법이 있습니까?

또한, 지금이 날 내가 봄과 JSF와 함께 쓴 모든 의문을 제기한다. 해당 필드에서 volatile 키워드를 사용하지 않으면 @Autowired 주석을 사용할 때 스레드 안전 클래스를 작성할 수 있습니까?

지금은 의존성 주입 프레임 워크를 사용하는 것이 정말 걱정됩니다. 컨테이너에 의해 주입 된 객체가 참조 또는 비 최신 상태로 null로 간주되지 않는다는 보장이 있습니까?

+0

모두 범위에 따라 달라집니다 ... – Kukeltje

+0

나는 그들이 없다고 말할 것입니다 ... 빈에 상태가 없습니다 ... 'JdbcTemplate'은 스레드 안전하며 가능한 상태로 간주되지 않습니다. 수정할 수 있습니다. –

답변

1

자동 설정할 콩 초기화 중에 주입되므로 요청을 처리 할 때,이 경우의 JdbcTemplate 널 않을 것.

@Component 
public class LoginDao { 

    private final JdbcTemplate jdbcTemplate; 

    @Autowired 
    public LoginDao(JdbcTemplate jdbcTemplate) { 
     this.jdbcTemplate = jdbcTemplate; 
    } 

    public List<Map<String, Object>> getUser(final String username, final String password) { 
     return jdbcTemplate.queryForList("select * from users where username=? and password=?", new Object[]{username, password}); 
    } 
} 
당신이 말한대로 효과적으로

, 자사의 여러 요청이 다른 스레드에 의해 처리됩니다 매우 가능하고, : 완전히 확인하려는 경우에는, 요는 권장되는 방법입니다 생성자,를 통해 삽입 할 수 어떤 일이 일어날지는 정의 된 범위에 따라 달라집니다.

  • 봄의 기본 범위는 'singleton'이므로이 경우 LoginDAO는 응용 프로그램에서 모든 요청을 처리하는 인스턴스를 하나만 갖습니다. 게시 된 코드에서 JdbcTemplate은 스레드로부터 안전하기 때문에 이것은 문제가되지 않습니다.

또한, 지금이 날 내가 봄 과 JSF와 함께 쓴 모든 의문을 제기한다. 그 필드에서 volatile 키워드를 사용하지 않으면 @Autowired 주석을 사용할 때 스레드 안전 클래스를 작성할 수 있습니까?

그것의 완전히 가능. 그리고 그것은 당신이 필요로하는 것에 주로 집중할 것입니다. 당신은 쓰레드에 안전한 방식으로 작업을 수행하는 싱글 톤 빈을 가질 수 있으며 (사용하는 코드와 라이브러리에 의존한다), 또는 '요청 범위'로 작업하는 비 쓰레드 안전 빈을 가질 수있다 (즉, 하나의 빈 인스턴스 중간에있는 항목 (봄에는 5 가지 범위 유형이 있습니다).

완전히 다른 목적으로 필드를 휘발성으로 설정하십시오. 휘발성 키워드는 필드 값이 여러 스레드에서 지속적으로 수정된다는 것을 나타내므로 JVM은 경쟁 조건을 방지하기 위해 스레드 내에서 값을 캐시하지 않으며 원자 적 방식으로 asignations를 관리합니다. 이는 필드 값만 보호하지만 값이 객체 인 경우 해당 객체 내부의 값을 보호하지 않습니다.

저는 이제 의존성 주입 프레임 워크를 사용하는 것에 대해 걱정하고 있습니다. 내 말은, 에 의해 주입 된 객체가 참조 용으로 또는 최신 상태로 null로 간주되지 않는다는 보장이 있습니까?

적어도 내 경험으로 봄, 나는 그 문제가 발생하지 않았습니다. Spring은 시작시 모든 것을 준비하는 초기화 작업을 수행하므로 걱정할 필요가 없습니다. 그러나 프로그래머가 정확하게 자신의 문제에 대해 더 많은 안전을 제공하기 때문에 이전에 표시된 생성자 autowiring 메서드를 사용하는 것이 좋습니다.

+0

생성자를 사용하는 예제는 완벽하게 구성된 빈을 다른 스레드로 전달할 때 가시성을 보장하므로 응답에 체크 표시와 upvote가 표시됩니다. 글쎄, 당신이 가시성에 대해 말한 것을 이해하지만, 휘발성은 또한 객체를 퍼블리시 할 때 가시성을 보장합니다. 그럼에도 불구하고 귀하의 설명은 간단하고 간결한 설명입니다. 흠. 마지막 점에 대해서, 다시 한번 주입 문제는 비록 그 객체가 초기화되고 준비되어 있어도 그것을 사용하는 다른 쓰레드에 대해서는 그렇지 않다는 것을 알 수 있습니다. final을 가진 생성자 메소드가 열쇠라고 생각합니다. – katiex7

+0

당신 자신의 것을 사용하지 않는다면 쓰레드를 사용하고 Spring 제공 API를 사용하는 대신 Bean에 대한 직접 참조를 사용하면 그런 일이 일어날 수 있다고 생각할 수 없습니다. 사용 범위에 따라 싱글 톤 Bean이 이미 초기화되어 있거나 요청 범위 (요청 범위의 경우)마다 Bean을 초기화하고 해당 종류의 문제를 처리하는 Bean 프록시가 있습니다. 편집 : 스프링이 메인 스레드가 응용 프로그램 설정을 마칠 때까지 요청을 처리하지 않으므로 그 시점에서 콩이 이미 초기화됩니다. –