Spring 은 ThreadLocal 의 '자원 - 사무' 스 레 드 바 인 딩 디자인 을 바탕 으로 합 니 다.

8341 단어 threadLocal
제목 이 좀 꼬 였 습 니 다. 쉽게 말 하면 이 글 은 Spring 이 왜 ThreadLocal 을 사용 하여 자원 과 사 무 를 스 레 드 에 연결 하 는 지 설명 하고 자 합 니 다. 이 뒤에 어떤 원인 과 디자인 동기 가 있 는 지 분석 을 통 해 Spring 의 스 레 드 바 인 딩 체 제 를 더욱 명확 하 게 인식 할 수 있 습 니 다.본문 원문 링크:
http://blog.csdn.net/bluishglc/article/details/7784502 전재 출처 를 밝 혀 주세요!
"원본" 데이터 접근 쓰기
데이터 베이스 와 같은 사무 적 특성 을 가 진 모든 자원 시스템 을 방문 하 는 것 은 똑 같은 특징 을 가진다. 먼저 자원 에 접근 하 는 '파이프' 를 얻어 야 한다. 데이터 베이스 에 있어 서 이른바 '파이프' 는 JDBC 의 Connection 이 고 Hibernate 의 Session 이다. 그러면 '파이프' 를 통 해 일련의 읽 기와 쓰기 명령 을 내 릴 것 이다. 예 를 들 어 데이터 뱅 크 의 SQL 등 이다.마지막 으로 이 '파이프' 를 끊 고 이 자원 에 대한 연결 을 풀 것 입 니 다.Spring 에 서 는 자원 에 접근 하 는 '파이프' 로 자원 을 가리 키 기 때문에 JDBC 의 Connection 과 Hibernate 의 Session 은 모두 '자원' (Resource) 이 라 고 불 린 다.다른 한편, 자원 과 사 무 는 밀접 한 관 계 를 가진다. 업무 의 시작 과 제출 은 모두 특정한 '리 소스' 에서 진행 된다.Hibernate 의 경우 '원본' 데이터 접근 프로그램 이 다음 과 같이 쓰 입 니 다.
Session session = sessionFactory.openSession();//  “  ”
Transaction tx = null;
try {
    tx = session.beginTransaction(); //    
	....
	DomainObject domainObject = session.load(...); //      
	....
	domainObject.processSomeBusinessLogic();//      
	....
	session.save(domainObject); //         
	....
	myDao.save(anotherDomainObject); //         
	....
	session.commit(); //    
}
catch (RuntimeException e) {
    tx.rollback();
    throw e;
}
finally {
    session.close(); //    
}

상기 코드 의 사고방식 은 매우 솔직 하 다. 먼저 데이터베이스 '자원' 을 얻 은 다음 에 이 자원 에서 업 무 를 시작 하고 일련의 업무 계산 과 데이터 접근 이 섞 인 작업 을 거 친 후에 업 무 를 제출 하고 자원 을 방출 한다.
층 을 나 누 어 가 져 온 괴로움
많은 사람들 이 상기 코드 의 문 제 를 단번에 알 수 있 을 것 이 라 고 믿는다. 업무 논리 와 데이터 방문 이 섞 여 층 을 나 누 는 '금기' 를 범 했다.좋 은 레이 어 링 시스템 은 흔히 상기 코드 를 실현 한다. Service 를 사용 하여 업무 논 리 를 실현 하고 DAO 를 사용 하여 Service 에 데이터 접근 지원 을 제공한다.
어떤 서비스의 실현 클래스:
public class MyServiceImpl implements MyService {

	public void processBusiness(){
		
		//             ?NO!        API,“  "Service,     !
		//Session session = sessionFactory.openSession();
		//session.beginTransaction();
		....
		DomainObject domainObject = myDao.getDomainObject(...); //      
		....
		domainObject.processSomeBusinessLogic();//      
		....
		myDao.save(domainObject); //         
		....
		myDao.save(anotherDomainObject); //         
		....		
	}	
	....
}

어떤 DAO 의 Hibernate 구현 클래스:
public class MyDaoHibernateImpl implements MyDao {

	public void save(DomainObject domainObject){
		//             ?NO!                   
		//             ?       Service。
		//Session session = sessionFactory.openSession();
		//session.beginTransaction();
		....
		session.save(domainObject);
	}	
	....
}

모순 의 초점
'분 층' 의 측면 에서 볼 때 상기 방안 은 '완벽' 이 라 고 할 수 있 지만 현실 적 인 기술 문 제 를 피 했다. '자원 획득' (즉, session) 과 '사무 시작' 코드 를 어떻게 배치 합 니까?코드 에 주석 이 있 는 것 처럼 어디 에 두 어도 문제 가 있 는 것 같 습 니 다. '조 화 롭 지 못 한' 모순 처럼 보 입 니 다.만약 에 이 '조 화 롭 지 못 한' 모순 을 해결 하려 면 기술적 으로 두 가지 어 려 운 문 제 를 해결 해 야 한다.
  • 어떻게 사무 정계 (Transaction Demarcation) 를 투명 하 게 진행 합 니까?
  • '컨 텍스트' 를 어떻게 구축 하 는 지, 트 랜 잭 션 과 트 랜 잭 션 을 시작 할 때, 그리고 트 랜 잭 션 과정 에서 모든 데이터 접근 방법 이 '같은 자원' (데이터베이스 연결 / Hibernate Session) 을 '암시 적' 으로 얻 을 수 있 습 니 다.이른바 '암시 적' 이란 같은 자원 인 스 턴 스 를 매개 변수 로 데이터 접근 방법 에 전달 할 수 없다 는 것 을 말한다. 그렇지 않 으 면 반드시 데이터 액세스 층 의 상부 코드 가 데이터 액세스 전용 API 오염 문제 (즉, 분 층 을 파 헤 쳤 다) 가 발생 할 것 이다. 전체 변 수 를 사용 하면 안 된다. 전체 변 수 는 유일한 것 이기 때문에 하나의 데이터 베이스 연결 만 사용 하 는 것 을 용인 할 수 있 는 응용 이 없다.사용자 가 스 레 드 를 요청 하 는 다 중 스 레 드 웹 응용 환경 은 더욱 그렇다.

  • Spring 의 해결책
    Spring 은 AOP 기반 성명 식 사무 정 계 를 사용 하여 첫 번 째 문 제 를 해결 하 였 으 며, ThreadLocal 기반 자원 과 사무 스 레 드 를 연결 하여 두 번 째 문 제 를 성공 적 으로 해결 하 였 습 니 다.(spring 의 구체 적 인 실현 에 대해 제 다른 글 을 참고 할 수 있 습 니 다. Spring 소스 코드 분석 (1) Spring 트 랜 잭 션 제어 Hibernate 첫 번 째 문제 와 관련 된 소스 코드 는 주로:
    org. springframework. aop. framework. JdkDynamicAopProxy 와 org. springframework. transaction. interceptor. TransactionInterceptor
    두 번 째 문제 와 관련 된 소스 코드 는 주로:
    org. springframework. transaction. support. AbstractPlatformTransactionManager 와 org. springframework. transaction. support. TransactionSynchronizationManager)
    본 고 는 Spring 이 두 번 째 문 제 를 어떻게 해결 하 는 지 에 중심 을 두 고 이 문제 에 대해 두 가지 특별한 설명 이 필요 하 다.
  • '컨 텍스트': Spring 은 '스 레 드 컨 텍스트', 즉 Tread Local 을 사용 합 니 다. 이 유 는 매우 간단 합 니 다. 스 레 드 역할 도 메 인 변수 로 서 '암시 적' 으로 잘 얻 을 수 있 습 니 다. 즉, 현재 스 레 드 에서 이 변 수 를 직접 얻 을 수 있 습 니 다 (매개 변수 전달 을 피 할 수 있 습 니 다). 또한 전체 변수 처럼 역할 도 메 인 이 너무 크 지 않 고 전체 적 으로 하나의 인 스 턴 스 만 있 습 니 다.실제로 더 큰 배경 에서 볼 때 대부분의 spring 응용 은 B / S 구조의 웹 응용 으로 servlet 스 레 드 모델 의 영향 을 받 아 이러한 웹 응용 은 사용자 가 새로운 스 레 드 를 열 어 처리 하 기 를 요청 하 는 것 입 니 다. 이 배경 에서 spring 은 스 레 드 를 컨 텍스트 로 연결 하 는 자원 과 사 무 를 처리 하 는 방식 이 매우 적합 합 니 다.
  • '자원 과 업무 의 생명 주기': '스 레 드 바 인 딩' 이라는 글자 로 만 이해 하면 스 레 드 에 연 결 된 자원 과 업무 의 생명 주기 와 스 레 드 가 똑 같이 긴 것 으로 오해 하기 쉽다. 이것 은 잘못된 것 이다.실제로 자원 과 업무 의 생명 주 기 는 스 레 드 생명 주기 와 필연 적 인 관 계 를 가지 지 않 습 니 다. 다만 자원 과 업무 가 존재 할 때 Tread Local 의 형식 으로 스 레 드 에 연결 되 어 있 을 뿐 입 니 다.한편, 자원 의 생명 주기 와 업무 의 생명 주기 가 똑 같 습 니 다. 우 리 는 자원 - 사무 라 는 생명 주기 관 계 를 Connection - per - Transaction 또는 Session - Per - Transaction 이 라 고 부 릅 니 다.

  • Hibernate 는 스스로 풍족 하 게 생활 한다.
    우 리 는 에피소드 로 Hibernate 에 대해 이야기 했다.아마도 Session - Per - Transaction 에 대한 보편적 인 수 요 를 만족 시 키 기 위해 Hibernate 도 자신의 Session - Per - Transaction 모델 을 실 현 했 습 니 다. 바로 여러분 이 알 고 있 는 Session Factory. getCurrentSession () 입 니 다. 이 방법 은 현재 스 레 드 에 연 결 된 session 인 스 턴 스 를 되 돌려 줍 니 다. 현재 스 레 드 에 session 인 스 턴 스 가 없 으 면 ThreadLocal 형식 으로 현재 스 레 드 에 연 결 된 새로운 인 스 턴 스 를 만 듭 니 다.이 동시에 이 방법 으로 생 성 된 session 은 사실 session 대리 입 니 다. 이 대 리 는 내부 의 실제 session 에 다음 과 같은 동작 을 추가 합 니 다.
  • session 의 데이터 조작 방법 을 차단 하고 작업 을 수행 하기 전에 begaintrancation () 을 호출 하여 사 무 를 열 었 는 지 확인 합 니 다. 그렇지 않 으 면 이상 이 발생 합 니 다.이 점 은 session 에 대한 사용 이 항상 하나의 사 무 를 만 드 는 것 에서 시작 되 어야 한 다 는 것 을 확보 했다.
  • 커밋 이나 rollback 이후 세 션 이 자동 으로 종 료 됩 니 다.이 점 은 업무 제출 후 session 도 사용 할 수 없 도록 확보 했다.

  • 바로 이 두 가지 가 세 션 과 트 랜 잭 션 이 일치 하 는 생명 주 기 를 유지 하도록 확보 한 것 이다.
    모든 것 이 이렇게 진행 되 었 다.
    상기 장면 과 Spring 의 해결 방안 을 결합 하여 Spring 성명 성 사 무 를 사용 하여 좋 은 분 층 절 차 를 실현 했다. 그의 자원 과 사 무 는 Spring 의 통제 하에 이렇게 일 했다.
  • 현재 스 레 드 가 트 랜 잭 션 제어 가 필요 한 방법 (예 를 들 어 특정한 service 방법) 을 실행 하면 AOP 차단 을 통 해 spring 은 방법 이 실행 되 기 전에 데이터베이스 연결 이나 hibenate session 을 신청 합 니 다.
  • 자원 획득 에 성공 한 후 하나의 사 무 를 시작 합 니 다.
  • 자원 즉 데이터베이스 연결 또는 hibenate session 의 인 스 턴 스 를 현재 스 레 드 의 ThreadLocal 에 저장 합 니 다 (즉, 스 레 드 바 인 딩)
  • 방법 을 실행 하 는 과정 에서 데이터베이스 연결 이나 hibenate session 을 받 아 데이터 접근 을 해 야 하 는 곳 은 현재 스 레 드 의 ThreadLocal 에서 같은 데이터베이스 연결 이나 hibenate session 의 인 스 턴 스 를 꺼 내 서 작 동 합 니 다.
  • 방법 실행 이 끝 났 습 니 다. 마찬가지 로 AOP 를 통 해 차단 합 니 다. spring 은 현재 스 레 드 에 연 결 된 사 무 를 추출 합 니 다 (hibenate 에 있어 서 현재 스 레 드 에 연 결 된 Session Holder 인 스 턴 스 를 추출 하고 현재 session 과 transaction 인 스 턴 스 를 저장 합 니 다). 제출 을 실행 합 니 다.
  • 사무 제출 후 자원 을 방출 하고 현재 스 레 드 에 연 결 된 모든 대상 을 비 웁 니 다!
  • 이 스 레 드 이후 에 새로운 사무 가 시작 되면 모든 것 이 다시 시 작 됩 니 다. Spring 은 새로운 데이터 베 이 스 를 연결 하거나 hibenate session 인 스 턴 스 를 사용 하여 새로운 사 무 를 시작 합 니 다. 두 사 무 는 아무런 관계 가 없습니다.

  • 작은 총화
  • Connection - per - Transaction / session - Per - Transaction 은 거의 항상 당신 이 필요 로 하 는 것 입 니 다.
  • 가끔 은 이러한 변 수 를 원 합 니 다. 전체 변수 처럼 언제 어디서나 얻 을 수 있 고 전체적인 역할 영역 과 유일한 인 스 턴 스 를 원 하지 않 습 니 다. 그러면 ThreadLocal 은 바로 당신 이 필요 로 하 는 것 일 수 있 습 니 다.
  • 최근 기타 블 로그:
    Spring 소스 코드 분석 (1) Spring 트 랜 잭 션 제어 Hibernate
    데이터베이스 라 이브 러 리 분 표 (sharding) 시리즈 (3) 사용 프레임 워 크 또는 자체 개발 및 sharding 실현 차원 에 대한 고려
    데이터베이스 라 이브 러 리 시트 (sharding) 시리즈 (2) 전역 메 인 키 생 성 정책
    데이터베이스 라 이브 러 리 시트 (sharding) 시리즈 (1) 분할 실시 전략 및 예시

    좋은 웹페이지 즐겨찾기