2017-04-04 1 views
3

@EnableScheduling@EnableAsync으로 봄 부팅을 사용하고 있습니다.@Scheduled 메서드 내에서 Spring @Async 메서드 호출

나는 @Scheduled이라는 주석이 달린 메소드를 가지고 있습니다. 나는 더 많은 방법을 가지고 있으며, 이것들은 @Async으로 주석되어있다.

이제이 @Async 메서드를 @Scheduled 메서드에서 호출하고 비동기 메서드에서 현재 스레드의 이름을 출력합니다. 내가 보는 것은 모두 같은 스레드 이름을 가지고 있는데 실제로는 @Scheduled 메서드를 실행하는 스레드입니다.

비동기 메서드 실행이 표시되지 않습니다. 여기에 무슨 문제가 있습니까? 풀 한 스레드-1에서 : 여기

내 스케줄러 클래스 스레드에 의해 호출

@Component 
public class TaskScheduler { 
    private static final Logger logger = Logger.getLogger(TaskScheduler.class); 

    @Scheduled(fixedDelay = 10000) 
    public void ScheduledMethod() { 
     methodOne(); 
     methodTwo(); 
     methodThree(); 
    } 

    @Async 
    private void methodOne() { 
     logger.info("Method one called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 

    @Async 
    private void methodTwo() { 
     logger.info("Method two called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 

    @Async 
    private void methodThree() { 
     logger.info("Method three called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 
} 

출력

방법 1 내 응용 프로그램 부팅 클래스 다음

@SpringBootApplication 
@EnableScheduling 
@EnableAsync 
public class ApplicationBoot { 

    public static void main(String[] args) { 
     SpringApplication.run(ApplicationBoot.class, args); 
    } 
} 

입니다 Tue Apr 04 16:32:27 IST 2017

스레드에 의해 호출 된 메서드 2 : Tue Apr 04 16:32:27 IST 2017

스레드가 호출하는 메서드 3 : Tue Apr 04 16:32:27에서 pool-1-thread-1 IST 2017

+3

일부 코드 샘플 도움이 될 것입니다. – Manuel

+1

코드 외에도 구성 및 예제 출력을 게시하십시오. –

+0

@Manuel은 샘플 코드를 추가했습니다. –

답변

3

SchedulerThread PoolThreads으로 설정되지 않았을 수 있습니다. 당신은 풀 사이즈의 속성을 제공하지 않는 경우 docs

에서

는 기본 스레드 풀은 하나의 스레드를해야합니다.

8

설명

봄 인스턴스 주위에 프록시를 만듭니다. ScheduledMethod은 내부적으로 3 개의 메소드를 호출합니다.이 메소드는 프록시 화되지 않아 비동기 적이 지 않습니다.

cf. the documentation은 아래 볼 수 있듯이

당신이 객체 참조에 메소드를 호출하면 메소드는 해당 객체 참조에 직접 를 호출됩니다.

해결 방법이 문제 Spring AOP not working, when the method is called internally within a bean 을 볼 수 있지만 가장 좋은 개인 방법은 supported too없는 것을 The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen...

참고 문서에서 제안 된 하나입니다 때문에 프록시 기반으로

Spring의 AOP 프레임 워크의 성격, 보호 된 메소드는 정의에 의해 차단되지 않으며 JDK 프록시 인 (해당 사항 없음)이나 CGLIB 프록시 (여기는 techn 일반적으로 가능하지만 AOP 목적에는 권장되지 않음). 결과로 주어진 pointcut은 public 메서드 에 대해서만 일치합니다!

해결 방법 예를

@Component 
public class ServiceMethod { 
    private static final Logger logger = Logger.getLogger(ServiceMethod .class); 

    @Async 
    public void methodOne() { 
     logger.info("Method one called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 

    @Async 
    public void methodTwo() { 
     logger.info("Method two called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 

    @Async 
    public void methodThree() { 
     logger.info("Method three called by Thread : " + Thread.currentThread().getName() + " at " + new Date()); 
    } 
} 

@Component 
public class TaskScheduler { 
    private static final Logger logger = Logger.getLogger(TaskScheduler.class); 

    @Autowired 
    private ServiceMethod serviceMethod; 

    @Scheduled(fixedDelay = 10000) 
    public void ScheduledMethod() { 
     serviceMethod.methodOne(); 
     serviceMethod.methodTwo(); 
     serviceMethod.methodThree(); 
    } 
} 
관련 문제