introduction
In business processing, some businesses use asynchronous methods more reasonable. For example, in a certain business logic, some data is stored in the redis cache. The cache is just an auxiliary function. Success or failure will not have a fundamental impact on the main business. This process can be carried out through an asynchronous method.
In Spring, the method can be called asynchronously by setting the @Async annotation on the method. That is to say, the method will return immediately upon invocation, and the actual execution of this method is handed over to Spring's TaskExecutor to complete.
Code Example
The project is a normal Spring project, Spring configuration file:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="/schema/beans" xmlns:xsi="http:///2001/XMLSchema-instance" xmlns:context="/schema/context" xmlns:task="/schema/task" xsi:schemaLocation="/schema/beans /schema/beans/spring-beans-4. /schema/context /schema/context/ /schema/task /schema/task/"> <!-- Packet Scan --> <context:component-scan base-package=""/> <!-- Thread pool for performing asynchronous tasksTaskExecutor --> <task:executor pool-size="5" /> <task:annotation-driven executor="myexecutor"/> </beans>
Two Service classes:
package ; import org.; import org.; import ; import ; import ; import ; /** * Service */ @Service public class BusinessService { private static final Logger log = (); @Autowired private CacheService cacheService; public void doBusiness() { ("start to deal with our business"); (); ("comlete service operation"); } /** * Get the return value of the asynchronous method execution */ public void doBusinessWithAsyncReturn() throws ExecutionException, InterruptedException { ("start to deal with our business"); Future<String> future = (); (()); //() method will block ("comlete service operation"); } }
package ; import org.; import org.; import ; import ; import ; import ; import ; /** * Cache service */ @Service public class CacheService { private static final Logger log = (); @Async(value = "myexecutor") //Specify the TaskExecutor to execute the task public void cacheData() { try { (3L); } catch (InterruptedException e) { (); } ("success store the result to cache"); } @Async public Future<String> cacheDataWithReturn() { try { (3L); } catch (InterruptedException e) { (); } ("success store the result to cache"); //The returned result needs to be wrapped by AsyncResult. return new AsyncResult<>("Async operation success"); } }
Test class:
package ; import ; import ; import ; import ; import ; import .junit4.SpringJUnit4ClassRunner; import ; @RunWith() @ContextConfiguration(locations = {"classpath:"}) public class MainTest { @Autowired private BusinessService businessService; @Test public void test() throws InterruptedException { (); //Don't let the main thread end too early, otherwise the console will not see the output content in the asynchronous method (5L); } @Test public void testAsyncReturn() throws Exception { (); (5L); } }
The result of executing the test() method:
22:20:33,207 INFO main :260 - Loaded default TestExecutionListener class names from location [META-INF/]: [, , , , , ]
22:20:33,226 INFO main :209 - Could not instantiate TestExecutionListener []. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
22:20:33,227 INFO main :187 - Using TestExecutionListeners: [@100fc185, @643b1d11, @2ef5e5e3, @36d4b5c, @6d00a15d]22:20:33,324 INFO main :317 - Loading XML bean definitions from class path resource []
22:20:33,585 INFO main :583 - Refreshing @4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:33,763 INFO main :165 - Initializing ExecutorService
22:20:33,766 INFO main $BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:33,767 INFO main $BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:34,107 ERROR main :24 - start to deal with our business
22:20:34,113 ERROR main :26 - comlete service operation
22:20:37,166 ERROR myexecutor-1 :28 - success store the result to cache
22:20:39,117 INFO Thread-0 :984 - Closing @4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:39,118 INFO Thread-0 :203 - Shutting down ExecutorService
The result of executing the testAsyncReturn() method:
21:38:16,908 INFO main :260 - Loaded default TestExecutionListener class names from location [META-INF/]: [, , , , , ]
21:38:16,926 INFO main :209 - Could not instantiate TestExecutionListener []. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [javax/servlet/ServletContext]
21:38:16,927 INFO main :187 - Using TestExecutionListeners: [@100fc185, @643b1d11, @2ef5e5e3, @36d4b5c, @6d00a15d]21:38:17,025 INFO main :317 - Loading XML bean definitions from class path resource []
21:38:17,263 INFO main :583 - Refreshing @4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:17,405 INFO main :165 - Initializing ExecutorService
21:38:17,407 INFO main $BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,407 INFO main $BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,692 ERROR main :35 - start to deal with our business
21:38:20,833 ERROR myexecutor-1 :39 - success store the result to cache
21:38:20,834 ERROR main :37 - Async operation success
21:38:20,835 ERROR main :38 - comlete service operation
21:38:25,838 INFO Thread-0 :984 - Closing @4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:25,839 INFO Thread-0 :203 - Shutting down ExecutorService
@Async's usage points
- Return value: Do not return value directly void; use AsyncResult or CompletableFuture to return value
- Customize the executor and specify for example: @Async("otherExecutor")
- @Async must be called between different classes: Class A—> Class B.C method() (@Async annotation is in Class B/Method). If it is called in the same class, it will be executed synchronously, for example: Class A.B()—> Class A.@Async C().
- @Async can also be added to the class, indicating that all methods of this class are executed asynchronously, and the annotations on the method will override the annotations on the class. But it is not usually used like this!
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.