12 Aralık 2019 Perşembe

SpringAsync @Async Anotasyonu

Giriş
Genelde servis sınıflarında kullanılır. Metod bir başka thread içinde çalıştırılır. Bu anotasyonu kullanabilmek için @EnableAsync anotasyonunun tanımlı olması gerekir. Açıklaması şöyle.
All that @Async does is execute the methods of the object on another thread, where it gets the thread from a pool (which can be specified, so some operations can have a dedicated pool).
Kısıtlar
1. @Async anotasyonu sadece bean'in public metodlarına uygulanır. Yani Async sınıfın bean olarak kullanılması gerekir. Açıklaması şöyle.
Suppose you write a class and identify a method which will act as Async and put @Async on top of that method, now if you want to use that class from another class by creating local instance then it will not fire the async, It has to be picked up by Spring @ComponentScan annotation or created inside a class marked as @Configuration.
2. Private metodlar @Async olamaz. Açıklaması şöyle.
Never use @Async on top of a private method as in runtime it will not able to create a proxy, so not working.
Açıklaması şöyle.
Please note that proxy mode allows for the interception of calls through the proxy only; local calls within the same class cannot get intercepted that way.
3. @Async Anotasyonu - Sonuç Tipi yazısına taşıdım

4. Exception handling için AsyncConfigurerSupport sınıfı ile tanımlanan exception handler kullanılır.

5. @Transactional ve @Async aynı metod üzerinde birlikte kullanılamaz.

@Transactional ve @Async Kullanımı
Örnek
Şöyle yaparız
@Slf4j
@Service
public class AsyncService {

  @Autowired
  public DataService dataService;

  @Async
  public void dbOperate(){
    log.info("some logic here first");
    dataService.allStep();
    log.info("some logic later");
  }
}

@Slf4j
@Service
public class DataService {

  @Transactional
  public void allStep(){
    saveObj();
    updateObj();
  }

  public void saveObj(){
    log.info("Some data saved");
  }

  public void updateObj(){
    log.info("Some another data updated");
  }
}
TaskExecutor Arayüzü İle İlişkisi
Açıklaması şöyle. Yani ismi taskExecutor olan bir thread pool aramaya başlar. Eğer yoksa yaratır
When you put an @Async annotation on a method, underlying it creates a proxy of that object where @Async is defined (JDK Proxy/CGlib) based on the proxyTargetClass property. Then Spring tries to find a thread pool associated with the context, to submit this method's logic as a separate path of execution to be exact it searches a unique TaskExecutor bean or a bean named as taskExecutor if not found then use default SimpleAsyncTaskExecutor.
Açıklaması şöyle
When you annotate a method with @Async annotation, it creates a proxy for that object based on “proxyTargetClass” property.

When spring executes this method, by default it will be searching for associated thread pool definition. Either a unique spring framework TaskExecutor bean in the context or Executor bean named “taskExecutor”. If neither of these two is resolvable, default it will use spring framework SimpleAsyncTaskExecutor to process async method execution.
@Async işlem için muhtemelen thread pool kullanacağımız için ThreadPoolTaskExecutor yaratmak gerekir.

value Alanı
Elimizde bir executor olsun
<task:annotation-driven executor="myExecutor"
  exception-handler="exceptionHandler"/>
<task:executor id="myExecutor" pool-size="7-42" queue-capacity="8"/>
Şöyle yaparız
@Async("myExecutor")
public void asynchronousFunction() throws InterruptedException {
  ...
}

Hiç yorum yok:

Yorum Gönder