복붙노트

[SPRING] 스레드 내의 범위가 지정된 프록시 bean에 액세스

SPRING

스레드 내의 범위가 지정된 프록시 bean에 액세스

Java 애플리케이션을 사용하여 성능을 향상시키기 위해 IO 집중적 인 작업을 병렬로 실행하기 위해 ThreadPool (Java 5 ExecutorService)을 사용하는 Tomcat에서 실행되는 웹 애플리케이션이 있습니다. 각각의 풀링 된 쓰레드 내에서 사용되는 빈들 중 일부를 요청 범위에두기를 원하지만, ThreadPool의 쓰레드는 스프링 컨텍스트에 접근 할 수없고 프록시 실패를 얻는다. ThreadPool의 스레드에서 스프링 컨텍스트를 사용하여 프록시 오류를 해결하는 방법에 대한 아이디어가 있습니까?

거기에 각 작업에 대한 봄 ThreadPool 각 스레드를 등록 / 등록을 방법이 있어야하지만 추측하고있어이 작업을 수행하는 방법을 찾는 모든 행운이 없었어요.

감사!

해결법

  1. ==============================

    1.요청 범위에 액세스해야하는 작업에 다음과 같은 수퍼 클래스를 사용하고 있습니다. 기본적으로 그것을 확장하고 onRun () 메서드에서 논리를 구현할 수 있습니다.

    요청 범위에 액세스해야하는 작업에 다음과 같은 수퍼 클래스를 사용하고 있습니다. 기본적으로 그것을 확장하고 onRun () 메서드에서 논리를 구현할 수 있습니다.

    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    
    /**
     * @author Eugene Kuleshov
     */
    public abstract class RequestAwareRunnable implements Runnable {
      private final RequestAttributes requestAttributes;
      private Thread thread;
    
      public RequestAwareRunnable() {
        this.requestAttributes = RequestContextHolder.getRequestAttributes();
        this.thread = Thread.currentThread();
      }
    
      public void run() {
        try {
          RequestContextHolder.setRequestAttributes(requestAttributes);
          onRun();
        } finally {
          if (Thread.currentThread() != thread) {
            RequestContextHolder.resetRequestAttributes();
          }
          thread = null;
        }
      }
    
      protected abstract void onRun();
    }
    
  2. ==============================

    2.나는 현재 받아 들여진 답변에 1000 표를줬으면 좋겠다. 얼마 동안이 일을하는 방법에 난처했다. 이를 기반으로 Spring 3.0에서 새로운 @Async 항목 중 일부를 사용하려는 경우 Callable 인터페이스를 사용하는 나의 해결책이 여기에 있습니다.

    나는 현재 받아 들여진 답변에 1000 표를줬으면 좋겠다. 얼마 동안이 일을하는 방법에 난처했다. 이를 기반으로 Spring 3.0에서 새로운 @Async 항목 중 일부를 사용하려는 경우 Callable 인터페이스를 사용하는 나의 해결책이 여기에 있습니다.

    public abstract class RequestContextAwareCallable<V> implements Callable<V> {
    
        private final RequestAttributes requestAttributes;
        private Thread thread;
    
        public RequestContextAwareCallable() {
            this.requestAttributes = RequestContextHolder.getRequestAttributes();
            this.thread = Thread.currentThread();
        }
    
        public V call() throws Exception {
            try {
                RequestContextHolder.setRequestAttributes(requestAttributes);
                return onCall();
            } finally {
                if (Thread.currentThread() != thread) {
                    RequestContextHolder.resetRequestAttributes();
                }
                thread = null;
            }
        }
    
        public abstract V onCall() throws Exception;
    }
    
  3. ==============================

    3.다른 방법으로 시도해 볼 수 있을까요? 요청 범위에 저장된 데이터 컨테이너를 사용하여 스레드 풀에 제공합니다 (스레드 풀이 한 번에 하나의 데이터 컨테이너를 가져 와서 작업하고 "완료"로 표시 한 다음 계속할 수 있도록 대기열에 넣을 수도 있음). 다음과 함께).

    다른 방법으로 시도해 볼 수 있을까요? 요청 범위에 저장된 데이터 컨테이너를 사용하여 스레드 풀에 제공합니다 (스레드 풀이 한 번에 하나의 데이터 컨테이너를 가져 와서 작업하고 "완료"로 표시 한 다음 계속할 수 있도록 대기열에 넣을 수도 있음). 다음과 함께).

  4. ==============================

    4.Spring에는 Spring에서 스레드 풀을 관리하는 데 사용할 수있는 ThreadPoolTaskExecutor 클래스가 있습니다. 그러나 각 스레드가 Spring 컨텍스트를 사용할 수있게하려면 약간의 작업을해야 할 것처럼 보입니다.

    Spring에는 Spring에서 스레드 풀을 관리하는 데 사용할 수있는 ThreadPoolTaskExecutor 클래스가 있습니다. 그러나 각 스레드가 Spring 컨텍스트를 사용할 수있게하려면 약간의 작업을해야 할 것처럼 보입니다.

    비록 당신이 그것을이 방법으로 묶었 다 할지라도 그것이 잘 작동하는지 나는 확신하지 못한다. Spring은 요청 (또는 세션) 범위의 객체를 찾기 위해 로컬 스레드의 토큰을 사용하므로 다른 스레드에서 요청 범위 Bean에 액세스하려는 경우 토큰이 존재하지 않을 가능성이 높습니다.

  5. from https://stackoverflow.com/questions/1528444/accessing-scoped-proxy-beans-within-threads-of by cc-by-sa and MIT license