欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中@Async異步失效的9種場(chǎng)景

 更新時(shí)間:2024年05月08日 09:39:22   作者:蘇三說(shuō)技術(shù)  
最近在項(xiàng)目某個(gè)方法使用@Async注解,但是該方法還是同步執(zhí)行了,異步不起作用,到底是什么原因呢?接下來(lái)本文給大家介紹了Java?@Async異步失效的9種場(chǎng)景,需要的朋友可以參考下

前言

最近有粉絲問(wèn)了我一個(gè)問(wèn)題:他在項(xiàng)目某個(gè)方法使用@Async注解,但是該方法還是同步執(zhí)行了,異步不起作用,到底是什么原因呢?

偽代碼如下:

@Slf4j
@Service
public?class?UserService?{

????@Async
????public?void?async(String?value)?{
????????log.info("async:" + value);
????}
}

這個(gè)問(wèn)題還是比較有意思的,今天這篇文章總結(jié)了@Async注解失效的9種場(chǎng)景,希望對(duì)你會(huì)有所幫助。

1 未使用@EnableAsync注解

在Spring中要開(kāi)啟@Async注解異步的功能,需要在項(xiàng)目的啟動(dòng)類,或者配置類上,使用@EnableAsync注解。

例如:

@EnableAsync
@SpringBootApplication(exclude?=?{DataSourceAutoConfiguration.class})
public?class?Application?{

????public?static?void?main(String[]?args)?{
????????SpringApplication.run(Application.class,?args);
????}
}

@EnableAsync注解相當(dāng)于一個(gè)開(kāi)關(guān),控制是否開(kāi)啟@Async注解異步的功能,默認(rèn)是關(guān)閉的。

如果在項(xiàng)目的啟動(dòng)類上沒(méi)使用@EnableAsync注解,則@Async注解異步的功能不生效。

2 內(nèi)部方法調(diào)用

我們?cè)谌粘i_(kāi)發(fā)中,經(jīng)常需要在一個(gè)方法中調(diào)用另外一個(gè)方法,例如:

@Slf4j
@Service
public?class?UserService?{

????public?void?test()?{
????????async("test");
????}

????@Async
????public?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

這個(gè)示例中,在UserService類中的test()方法中調(diào)用了async()方法。

如果在controller中@Autowired了UserService類的對(duì)象,調(diào)用了它的test()方法,則async()異步的功能會(huì)失效。

我們知道Spring通過(guò)@Async注解實(shí)現(xiàn)異步的功能,底層其實(shí)是通過(guò)Spring的AOP實(shí)現(xiàn)的,也就是說(shuō)它需要通過(guò)JDK動(dòng)態(tài)代理或者cglib,生成代理對(duì)象。

異步的功能,是在代理對(duì)象中增加的,我們必須調(diào)用代理對(duì)象的test()方法才行。

而在類中直接進(jìn)行方法的內(nèi)部調(diào)用,在test()方法中調(diào)用async()方法,調(diào)用的是該類原對(duì)象的async方法,相當(dāng)于調(diào)用了this.async()方法,而并非UserService代理類的async()方法。

因此,像這種內(nèi)部方法調(diào)用,@Async注解的異步功能會(huì)失效。

3 方法非public

在Java中有4種權(quán)限修飾符

  • public:所有類都可以訪問(wèn)。
  • private:只能同一個(gè)類訪問(wèn)。
  • protected:同一個(gè)類,同一個(gè)包下的其他類,不同包下的子類可以訪問(wèn)。
  • 默認(rèn)修飾符:同一個(gè)類,同一個(gè)包下的其他類可以訪問(wèn)。

在實(shí)際工作中,我們使用頻率最高的可能是public和private了。

如果我在定義Service類中的某個(gè)方法時(shí),有時(shí)把權(quán)限修飾符定義錯(cuò)了,例如:

@Slf4j
@Service
public?class?UserService?{

????@Async
????private?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

這個(gè)例子中將UserService類的async()方法的權(quán)限修飾符定義成了private的,這樣@Async注解也會(huì)失效。

因?yàn)閜rivate修飾的方法,只能在UserService類的對(duì)象中使用。

而@Async注解的異步功能,需要使用Spring的AOP生成UserService類的代理對(duì)象,該代理對(duì)象沒(méi)法訪問(wèn)UserService類的private方法,因此會(huì)出現(xiàn)@Async注解失效的問(wèn)題。

4 方法返回值錯(cuò)誤

我們?cè)趯?xiě)一個(gè)新的方法時(shí),經(jīng)常需要定義方法的返回值。

返回值可以是void、int、String、User等等,但如果返回值定義錯(cuò)誤,也可能會(huì)導(dǎo)致@Async注解的異步功能失效。

例如:

@Service
public?class?UserService?{

????@Async
????public?String?async(String?value)?{
????????log.info("async:{}",?value);
????????return?value;
????}
}

UserService類的async方法的返回值是String,這種情況竟然會(huì)導(dǎo)致@Async注解的異步功能失效。

在AsyncExecutionInterceptor類的invoke()方法,會(huì)調(diào)用它的父類AsyncExecutionAspectSupport中的doSubmit方法,該方法時(shí)異步功能的核心代碼,如下:

從圖中看出,@Async注解的異步方法的返回值,要么是Future,要么是null。

因此,在實(shí)際項(xiàng)目中,如果想要使用@Async注解的異步功能,相關(guān)方法的返回值必須是void或者Future。

5 方法用static修飾了

有時(shí)候,我們的方法會(huì)使用static修飾,這樣在調(diào)用的地方,可以直接使用類名.方法名,訪問(wèn)該方法了。

但如果在@Async方法上加了static修飾符,例如:

@Slf4j
@Service
public?class?UserService?{

????@Async
????public?static?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

這時(shí)@Async的異步功能會(huì)失效,因?yàn)檫@種情況idea會(huì)直接報(bào)錯(cuò):Methods annotated with '@Async' must be overridable 。

使用@Async注解聲明的方法,必須是能被重寫(xiě)的,很顯然static修飾的方法,是類的靜態(tài)方法,是不允許被重寫(xiě)的。

因此這種情況下,@Async注解的異步功能會(huì)失效。

6 方法用final修飾

在Java種final關(guān)鍵字,是一個(gè)非常特別的存在。

用final修飾的類,沒(méi)法被繼承。

用final修飾的方法,沒(méi)法被重寫(xiě)。

用final修飾的變量,沒(méi)法被修改。

如果final使用不當(dāng),也會(huì)導(dǎo)致@Async注解的異步功能失效,例如:

@Slf4j
@Service
public?class?UserService?{

????public?void?test()?{
????????async("test");
????}

????@Async
????public??final?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

這種情況下idea也會(huì)直接報(bào)錯(cuò):Methods annotated with '@Async' must be overridable 。

因?yàn)槭褂胒inal關(guān)鍵字修飾的方法,是沒(méi)法被子類重寫(xiě)的。

因此這種情況下,@Async注解的異步功能會(huì)失效。

7 業(yè)務(wù)類沒(méi)加@Service注解

有時(shí)候,我們?cè)谛录覵ervice類時(shí),會(huì)忘了加@Service注解,例如:

@Slf4j
//@Service
public?class?UserService?{

????@Async
????public?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

@Service
public?class?TestService?{

???@Autowired
???private?UserService?userService;

????public?void?test()?{
????????userService.async("test");
????}
}

這種情況下,@Async注解異步的功能也不會(huì)生效。因?yàn)閁serService類沒(méi)有使用@Service、@Component或者@Controller等注解聲明,該類不會(huì)被Spring管理,因此也就無(wú)法使用Spring的異步功能。

8 自己new的對(duì)象

在項(xiàng)目中,我們經(jīng)常需要new一個(gè)對(duì)象,然后對(duì)他賦值,或者調(diào)用它的方法。

但如果new了一個(gè)Service類的對(duì)象,可能會(huì)出現(xiàn)一些意想不到的問(wèn)題,例如:

@Slf4j
@Service
public?class?UserService?{

????@Async
????public?void?async(String?value)?{
????????log.info("async:{}",?value);
????}
}

@Service
public?class?TestService?{

????public?void?test()?{
????????UserService?userService?=?new?UserService();
????????userService.async("test");
????}
}

在TestService類的test()方法中,new了一個(gè)UserService類的對(duì)象,然后調(diào)用該對(duì)象的async()方法。

很顯然這種情況下,async()方法只能同步執(zhí)行,沒(méi)法異步執(zhí)行。

因?yàn)樵陧?xiàng)目中,我們自己new的對(duì)象,不會(huì)被Spring管理,因此也就無(wú)法使用Spring的異步功能。

不過(guò)我們可以通過(guò)BeanPostProcessor類,將創(chuàng)建的對(duì)象手動(dòng)注入到Spring容器中。

9 Spring無(wú)法掃描異步類

我們?cè)赟pring項(xiàng)目中可以使用@ComponentScan注解指定項(xiàng)目中掃描的包路徑,例如:

@ComponentScan({"com.susan.demo.service1"})
@SpringBootApplication(exclude?=?{DataSourceAutoConfiguration.class})
public?class?Application?{

????public?static?void?main(String[]?args)?{
????????SpringApplication.run(Application.class,?args);
????}
}

項(xiàng)目中com.susan.demo.service1這個(gè)路徑是不存在的,會(huì)導(dǎo)致@Async注解異步的功能失效。

同時(shí)如果@ComponentScan注解定義的路徑,沒(méi)有包含你新加的Servcie類的路徑,@Async注解異步的功能也會(huì)失效。

以上就是Java中@Async異步失效的9種場(chǎng)景的詳細(xì)內(nèi)容,更多關(guān)于Java @Async異步失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java8的Optional如何干掉空指針(示例詳解)

    Java8的Optional如何干掉空指針(示例詳解)

    這篇文章主要介紹了Java8的Optional如何干掉空指針,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • springboot中redis的緩存穿透問(wèn)題實(shí)現(xiàn)

    springboot中redis的緩存穿透問(wèn)題實(shí)現(xiàn)

    這篇文章主要介紹了springboot中redis的緩存穿透問(wèn)題實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java中ArrayList的removeAll方法詳解

    Java中ArrayList的removeAll方法詳解

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList的removeAll方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)看看吧。
    2017-07-07
  • Spring Cloud使用Feign實(shí)現(xiàn)Form表單提交的示例

    Spring Cloud使用Feign實(shí)現(xiàn)Form表單提交的示例

    本篇文章主要介紹了Spring Cloud使用Feign實(shí)現(xiàn)Form表單提交的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Mybatis基于注解形式的sql語(yǔ)句生成實(shí)例代碼

    Mybatis基于注解形式的sql語(yǔ)句生成實(shí)例代碼

    這篇文章主要介紹了 Mybatis基于注解形式的sql語(yǔ)句生成實(shí)例代碼,需要的朋友可以參考下
    2017-09-09
  • Spring Cloud動(dòng)態(tài)配置刷新@RefreshScope與@Component的深度解析

    Spring Cloud動(dòng)態(tài)配置刷新@RefreshScope與@Component的深度解析

    在現(xiàn)代微服務(wù)架構(gòu)中,動(dòng)態(tài)配置管理是一個(gè)關(guān)鍵需求,Spring Cloud 提供了 @RefreshScope 注解,允許應(yīng)用在運(yùn)行時(shí)動(dòng)態(tài)更新配置,而無(wú)需重啟服務(wù),本文深入探析Spring Cloud動(dòng)態(tài)配置刷新@RefreshScope與@Component,感興趣的朋友一起看看吧
    2025-04-04
  • Springboot+WebSocket實(shí)現(xiàn)一對(duì)一聊天和公告的示例代碼

    Springboot+WebSocket實(shí)現(xiàn)一對(duì)一聊天和公告的示例代碼

    這篇文章主要介紹了Springboot+WebSocket實(shí)現(xiàn)一對(duì)一聊天和公告的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • AJAX?SpringBoot?前后端數(shù)據(jù)交互的項(xiàng)目實(shí)現(xiàn)

    AJAX?SpringBoot?前后端數(shù)據(jù)交互的項(xiàng)目實(shí)現(xiàn)

    本文主要介紹了AJAX?SpringBoot?前后端數(shù)據(jù)交互的項(xiàng)目實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Java中數(shù)組的一些常見(jiàn)操作和技巧分析

    Java中數(shù)組的一些常見(jiàn)操作和技巧分析

    這篇文章主要給大家介紹了關(guān)于Java中數(shù)組的一些常見(jiàn)操作和技巧分析的相關(guān)資料,數(shù)組(Array)是Java中的一種引用數(shù)據(jù)類型,是多個(gè)相同類型數(shù)據(jù)一定順序排列的集合,并使用一個(gè)名字命名,并通過(guò)編號(hào)的方式對(duì)這些數(shù)據(jù)進(jìn)行統(tǒng)一管理,需要的朋友可以參考下
    2023-08-08
  • 淺談cookie 和session 的區(qū)別

    淺談cookie 和session 的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談cookie 和session 的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06

最新評(píng)論