Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用
這篇文章主要介紹了Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
在我們使用spring框架的過(guò)程中,在很多時(shí)候我們會(huì)使用@async注解來(lái)異步執(zhí)行某一些方法,提高系統(tǒng)的執(zhí)行效率。今天我們來(lái)探討下 spring 是如何完成這個(gè)功能的。
spring 在掃描bean的時(shí)候會(huì)掃描方法上是否包含@async的注解,如果包含的,spring會(huì)為這個(gè)bean動(dòng)態(tài)的生成一個(gè)子類(lèi),我們稱之為代理類(lèi)(?), 代理類(lèi)是繼承我們所寫(xiě)的bean的,然后把代理類(lèi)注入進(jìn)來(lái),那此時(shí),在執(zhí)行此方法的時(shí)候,會(huì)到代理類(lèi)中,代理類(lèi)判斷了此方法需要異步執(zhí)行,就不會(huì)調(diào)用父類(lèi) (我們?cè)緦?xiě)的bean)的對(duì)應(yīng)方法。spring自己維護(hù)了一個(gè)隊(duì)列,他會(huì)把需要執(zhí)行的方法,放入隊(duì)列中,等待線程池去讀取這個(gè)隊(duì)列,完成方法的執(zhí)行, 從而完成了異步的功能。
我們可以關(guān)注到再配置task的時(shí)候,是有參數(shù)讓我們配置線程池的數(shù)量的。因?yàn)檫@種實(shí)現(xiàn)方法,所以在同一個(gè)類(lèi)中的方法調(diào)用,添加@async注解是失效的!,原因是當(dāng)你在同一個(gè)類(lèi)中的時(shí)候,方法調(diào)用是在類(lèi)體內(nèi)執(zhí)行的,spring無(wú)法截獲這個(gè)方法調(diào)用。
那在深入一步,spring為我們提供了AOP,面向切面的功能。他的原理和異步注解的原理是類(lèi)似的,spring在啟動(dòng)容器的時(shí)候,會(huì)掃描切面所定義的 類(lèi)。在這些類(lèi)被注入的時(shí)候,所注入的也是代理類(lèi),當(dāng)你調(diào)用這些方法的時(shí)候,本質(zhì)上是調(diào)用的代理類(lèi)。通過(guò)代理類(lèi)再去執(zhí)行父類(lèi)相對(duì)應(yīng)的方法,那spring只 需要在調(diào)用之前和之后執(zhí)行某段代碼就完成了AOP的實(shí)現(xiàn)了!
那最后我們還有一個(gè)問(wèn)題,spring是如何動(dòng)態(tài)的生成某一個(gè)類(lèi)的子類(lèi)的?代理類(lèi)?
簡(jiǎn)單介紹:
Spring為任務(wù)調(diào)度與異步方法執(zhí)行提供了注解支持。通過(guò)在方法上設(shè)置@Async注解,可使得方法被異步調(diào)用。也就是說(shuō)調(diào)用者會(huì)在調(diào)用時(shí)立即返回,而被調(diào)用方法的實(shí)際執(zhí)行是交給Spring的TaskExecutor來(lái)完成。
開(kāi)啟@Async注解:
<task:annotation-driven executor="annotationExecutor" /> <!-- 支持 @Async 注解 --> <task:executor id="annotationExecutor" pool-size="20"/>
同時(shí)加入<context:component-scan />掃描注解。
為了比較,先來(lái)一個(gè)同步調(diào)用:
@Component
public class TestAsyncBean {
public void sayHello4() throws InterruptedException {
Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
System.out.println("我愛(ài)你啊!");
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Test
public void test_sayHello4() throws InterruptedException, ExecutionException {
System.out.println("你不愛(ài)我了么?");
testAsyncBean.sayHello4();
System.out.println("回的這么慢, 你肯定不愛(ài)我了, 我們還是分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進(jìn)程過(guò)早結(jié)束
}
}
輸出結(jié)果:
你不愛(ài)我了么? 我愛(ài)你啊! 回的這么慢, 你肯定不愛(ài)我了, 我們還是分手吧。。。
同步調(diào)用會(huì)按代碼順序依次進(jìn)行下去,如果哪里需要等待,那么就阻塞在那里,不再向下繼續(xù)進(jìn)行。
使用@Async的異步調(diào)用:
@Component
public class TestAsyncBean {
@Async
public void sayHello3() throws InterruptedException {
Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
System.out.println("我愛(ài)你啊!");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello3() throws InterruptedException, ExecutionException {
System.out.println("你不愛(ài)我了么?");
testAsyncBean.sayHello3();
System.out.println("你竟無(wú)話可說(shuō), 我們分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進(jìn)程過(guò)早結(jié)束
}
}
輸出結(jié)果:
你不愛(ài)我了么? 你竟無(wú)話可說(shuō), 我們分手吧。。。 我愛(ài)你啊!
異步調(diào)用,通過(guò)開(kāi)啟新的線程來(lái)執(zhí)行調(diào)用的方法,不影響主線程。異步方法實(shí)際的執(zhí)行交給了Spring的TaskExecutor來(lái)完成。
上面這種方式是沒(méi)有返回值的,下面嘗試有返回值的異步調(diào)用:
@Component
public class TestAsyncBean {
@Async
public String sayHello2() throws InterruptedException {
Thread.sleep(2 * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
return "我愛(ài)你啊!";// 調(diào)用方調(diào)用后會(huì)立即返回,所以返回null
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello2() throws InterruptedException, ExecutionException {
System.out.println("你不愛(ài)我了么?");
System.out.println(testAsyncBean.sayHello2());
System.out.println("你說(shuō)的啥? 我們還是分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進(jìn)程過(guò)早結(jié)束
}
}
輸出結(jié)果:
你不愛(ài)我了么? null 你說(shuō)的啥? 我們還是分手吧。。。
通過(guò)直接獲取返回值得方式是不行的,這里就需要用到異步回調(diào),異步方法返回值必須為Future<>,就像Callable與Future。
下面通過(guò)AsyncResult<>來(lái)獲得異步調(diào)用的返回值:
@Component
public class TestAsyncBean {
@Async
public Future<String> sayHello1() throws InterruptedException {
int thinking = 2;
Thread.sleep(thinking * 1000);//網(wǎng)絡(luò)連接中 。。。消息發(fā)送中。。。
System.out.println("我愛(ài)你啊!");
return new AsyncResult<String>("發(fā)送消息用了"+thinking+"秒");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello1() throws InterruptedException, ExecutionException {
Future<String> future = null;
System.out.println("你不愛(ài)我了么?");
future = testAsyncBean.sayHello1();
System.out.println("你竟無(wú)話可說(shuō), 我們分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進(jìn)程過(guò)早結(jié)束
System.out.println(future.get());
}
}
輸出結(jié)果:
你不愛(ài)我了么? 你竟無(wú)話可說(shuō), 我們分手吧。。。 我愛(ài)你啊!
發(fā)送消息用了2秒
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Spring Boot利用@Async異步調(diào)用:使用Future及定義超時(shí)詳解
- Spring Boot利用@Async異步調(diào)用:ThreadPoolTaskScheduler線程池的優(yōu)雅關(guān)閉詳解
- Spring Boot異步調(diào)用@Async過(guò)程詳解
- Spring Boot利用@Async如何實(shí)現(xiàn)異步調(diào)用:自定義線程池
- 深入理解spring boot異步調(diào)用方式@Async
- spring boot 使用@Async實(shí)現(xiàn)異步調(diào)用方法
- spring boot中使用@Async實(shí)現(xiàn)異步調(diào)用任務(wù)
- 深入理解Spring注解@Async解決異步調(diào)用問(wèn)題
相關(guān)文章
Java實(shí)現(xiàn)分頁(yè)的幾種方法詳細(xì)解析
這篇文章主要介紹了Java實(shí)現(xiàn)分頁(yè)的幾種方法詳細(xì)解析,在Java中想實(shí)現(xiàn)分頁(yè)功能有幾種常用的方法,今天我們就來(lái)詳細(xì)解析一下,文中提供了解決思路和部分實(shí)現(xiàn)代碼,需要的朋友可以參考下2023-11-11
java Apache poi 對(duì)word doc文件進(jìn)行讀寫(xiě)操作
這篇文章主要介紹了Apache poi 對(duì)word doc文件進(jìn)行讀寫(xiě)操作的相關(guān)資料,需要的朋友可以參考下2017-01-01
Spring Boot 中application.yml與bootstrap.yml的區(qū)別
其實(shí)yml和properties文件是一樣的原理,且一個(gè)項(xiàng)目上要么yml或者properties,二選一的存在。這篇文章給大家介紹了Spring Boot 中application.yml與bootstrap.yml的區(qū)別,感興趣的朋友一起看看吧2018-04-04
Java?工具類(lèi)實(shí)現(xiàn)音頻音量提升
本文主要介紹了可以將音頻提升音量的一個(gè)java工具類(lèi)示例代碼,代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴來(lái)了解一下吧,,希望能夠給你帶來(lái)幫助2021-11-11

