Asynchronous processing with @Async in Spring
Asynchronous processing with @Async in Spring
1.Overview Overview
In this article, we will look at asynchronous execution support and @Async annotation in Spring . Simply put, if you put the @Async annotation in an empty bean , it will be executed in a separate thread. For example, the caller does not have to wait for the called method to complete.2. Turn on Async function Enable Async Support
Java settings Java configuration asynchronous processing by enabling asynchronous processing Just add the @EnableAsync to simply set the class to write :@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }
The above annotation is sufficient, but you can also set some options you need:
annotation – default, @EnableAsync detectsSpring's Async annotations and EJB 3.1 javax.ejb.Asynchronous ; Other annotations customized with this option can also be detected.
mode – indicatesthe type of advice to use-based on JDK proxy or AspectJ weaving.
proxyTargetClass -indicates the type of proxy to use-CGLIB or JDK; This property value is valid only when mode is set to AdviceMode.PROXY .
order – sets the order in which AsyncAnnotationBeanPostProcessor should apply; It isrun from the end by default toonly consider all existing proxies .
Asynchronous processing can also be enabled via XML configuration using the task namespace :
<task:executor id="myexecutor" pool-size="5" />
<task:annotation-driven executor="myexecutor"/>
3. The @Async Annotation
Let's look at the rules first-@Async has two limitations:1. Apply only to public methods
2. Self-invocation self invocation – call the async method in the same class – does not work
The reason for this is simple, because the method must be public to become a proxy, and self-calling does not work because it bypasses the proxy and calls the method directly .
There is no return type Method Methods with void Return Type
A method with a return type of void works asynchronously with the following simple configuration:
@Async
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. " + Thread.currentThread().getName());
}
Methods that have a return type Methods with Return Type
@Async can be applied to a method with return type: by putting the actual return value in the Future object.
@Async
public Future<String> asyncMethodWithReturnType() {
System.out.println("Execute method asynchronously - " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
return new AsyncResult<String>("hello world !!!!");
} catch (InterruptedException e) {
//
}
return null;
}
Spring also provides an AsyncResult class that implements Future , which is used to get the results of asynchronous method execution.
Now let's call the above method and use the Future object to get the result of the asynchronous processing .
public void testAsyncAnnotationForMethodsWithReturnType()
throws InterruptedException, ExecutionException {
System.out.println("Invoking an asynchronous method. "
+ Thread.currentThread().getName());
Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();
while (true) {
if (future.isDone()) {
System.out.println("Result from asynchronous process - " + future.get());
break;
}
System.out.println("Continue doing something else. ");
Thread.sleep(1000);
}
}
4. The Executor
Spring uses SimpleAsyncTaskExecutor by default to execute real methods asynchronously. The default setting can be overridden in two levels-application level or private method level.To override a method-level practitioners Override the Executor at the Method Level
You need to declare the necessary executors in your configuration class:
@Configuration
@EnableAsync
public class SpringAsyncConfig {
@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
}
After that, you must provide the executor name as an attribute value in @Async :
@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
System.out.println("Execute method with configured executor - " + Thread.currentThread().getName());
}
To override the application level practitioners to Override the Executor at the Application Level
In this case, the configuration class must implement the AsyncConfigurer interface-which means that it must implement the getAsyncExecutor () method. Here we will return the executor for the entire application-this is now the default executor for executing methods annotated with @Async.
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
}
}
5. Exception Handling
If the method's return type is Future, exception handling is easy-the Future.get () method throws an exception.However, when the return type is void, the exception will not be delivered to the calling thread. Therefore, we need additional settings for exception handling.
We will create a custom asynchronous exception handler by implementing the AsyncUncaughtExceptionHandler interface. The handleUncaughtException () method is called when an uncaught asynchronous exception is caught :
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
System.out.println("Exception message - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
}
}
In the previous section, we saw the AsyncConfigurer interface implemented by the configuration class . As part of that, we also need to override the getAsyncUncaughtExceptionHandler () method, which returns our custom asynchronous exception handler :
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
Comments
Post a Comment