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="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <!-- Package Scan --> <context:component-scan base-package="com.lzumetal.ssm"/> <!-- Thread pool for executing asynchronous tasks TaskExecutor --> <task:executor id="myexecutor" pool-size="5" /> <task:annotation-driven executor="myexecutor"/></beans>
Two Service classes:
package com.lzumetal.ssm.anotation.service;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;/** * Business Service */@Servicepublic class BusinessService { private static final Logger log = LoggerFactory.getLogger(BusinessService.class); @Autowired private CacheService cacheService; public void doBusiness() { log.error("start to deal with our business"); cacheService.cacheData(); log.error("comlete service operation"); } /** * Get the return value for asynchronous method execution*/ public void doBusinessWithAsyncReturn() throws ExecutionException, InterruptedException { log.error("start to deal with our business"); Future<String> future = cacheService.cacheDataWithReturn(); log.error(future.get()); //future.get() method is a blocking log.error("comlete service operation"); }} package com.lzumetal.ssm.anotation.service;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.scheduling.annotation.Async;import org.springframework.scheduling.annotation.AsyncResult;import org.springframework.stereotype.Service;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;/** * Cache Service*/@Servicepublic class CacheService { private static final Logger log = LoggerFactory.getLogger(CacheService.class); @Async(value = "myexecutor") //Specify the TaskExecutor to execute the task public void cacheData() { try { TimeUnit.SECONDS.sleep(3L); } catch (InterruptedException e) { e.printStackTrace(); } log.error("success store the result to cache"); } @Async public Future<String> cacheDataWithReturn() { try { TimeUnit.SECONDS.sleep(3L); } catch (InterruptedException e) { e.printStackTrace(); } log.error("success store the result to cache"); //The returned result needs to be wrapped by the AsyncResult class return new AsyncResult<>("Async operation success"); }}Test class:
package com.lzumetal.ssm.anotation.test;import com.lzumetal.ssm.anotation.service.BusinessService;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.concurrent.TimeUnit;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring-context.xml"})public class MainTest { @Autowired private BusinessService businessService; @Test public void test() throws InterruptedException { businessService.doBusiness(); //Don't let the main thread end too early, otherwise the console will not see the output content in the asynchronous method TimeUnit.SECONDS.sleep(5L); } @Test public void testAsyncReturn() throws Exception { businessService.doBusinessWithAsyncReturn(); TimeUnit.SECONDS.sleep(5L); }}The result of executing the test() method:
22:20:33,207 INFO main support.DefaultTestContextBootstrapper:260 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
22:20:33,226 INFO main support.DefaultTestContextBootstrapper:209 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. 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 support.DefaultTestContextBootstrapper:187 - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@100fc185, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@643b1d11, org.springframework.test.context.support.DirtiesContextTestExecutionListener@2ef5e5e3, org.springframework.test.context.transaction.TransactionalTestExecutionListener@36d4b5c, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6d00a15d]22:20:33,324 INFO main xml.XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [spring-context.xml]
22:20:33,585 INFO main support.GenericApplicationContext:583 - Refreshing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:33,763 INFO main concurrent.ThreadPoolTaskExecutor:165 - Initializing ExecutorService
22:20:33,766 INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.config.TaskExecutorFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:33,767 INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:20:34,107 ERROR main service.BusinessService:24 - start to deal with our business
22:20:34,113 ERROR main service.BusinessService:26 - complete service operation
22:20:37,166 ERROR myexecutor-1 service.CacheService:28 - success store the result to cache
22:20:39,117 INFO Thread-0 support.GenericApplicationContext:984 - Closing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 22:20:33 CST 2018]; root of context hierarchy
22:20:39,118 INFO Thread-0 concurrent.ThreadPoolTaskExecutor:203 - Shutting down ExecutorService
The result of executing the testAsyncReturn() method:
21:38:16,908 INFO main support.DefaultTestContextBootstrapper:260 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
21:38:16,926 INFO main support.DefaultTestContextBootstrapper:209 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. 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 support.DefaultTestContextBootstrapper:187 - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@100fc185, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@643b1d11, org.springframework.test.context.support.DirtiesContextTestExecutionListener@2ef5e5e3, org.springframework.test.context.transaction.TransactionalTestExecutionListener@36d4b5c, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6d00a15d]21:38:17,025 INFO main xml.XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [spring-context.xml]
21:38:17,263 INFO main support.GenericApplicationContext:583 - Refreshing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:17,405 INFO main concurrent.ThreadPoolTaskExecutor:165 - Initializing ExecutorService
21:38:17,407 INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.config.TaskExecutorFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,407 INFO main support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:325 - Bean 'myexecutor' of type [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
21:38:17,692 ERROR main service.BusinessService:35 - start to deal with our business
21:38:20,833 ERROR myexecutor-1 service.CacheService:39 - success store the result to cache
21:38:20,834 ERROR main service.BusinessService:37 - Async operation success
21:38:20,835 ERROR main service.BusinessService:38 - complete service operation
21:38:25,838 INFO Thread-0 support.GenericApplicationContext:984 - Closing org.springframework.context.support.GenericApplicationContext@4f7d0008: startup date [Wed May 30 21:38:17 CST 2018]; root of context hierarchy
21:38:25,839 INFO Thread-0 concurrent.ThreadPoolTaskExecutor:203 - Shutting down ExecutorService
@Async's usage points
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.