偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

@Async注解失效的九種場景

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

前言

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

偽代碼如下:

@Slf4j
@Service
public class UserService {

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

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

圖片圖片

1 未使用@EnableAsync注解

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

例如:

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

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

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

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

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

我們在日常開發(fā)中,經(jīng)常需要在一個方法中調(diào)用另外一個方法,例如:

@Slf4j
@Service
public class UserService {

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

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

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

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

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

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

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

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

3 方法非public

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

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

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

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

@Slf4j
@Service
public class UserService {

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

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

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

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

4 方法返回值錯誤

我們在寫一個新的方法時,經(jīng)常需要定義方法的返回值。

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

例如:

@Service
public class UserService {

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

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

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

圖片圖片

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

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

5 方法用static修飾了

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

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

@Slf4j
@Service
public class UserService {

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

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

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

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

6 方法用final修飾

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

用final修飾的類,沒法被繼承。

用final修飾的方法,沒法被重寫。

用final修飾的變量,沒法被修改。

如果final使用不當(dāng),也會導(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也會直接報錯:Methods annotated with '@Async' must be overridable 。

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

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

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

有時候,我們在新加Service類時,會忘了加@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注解異步的功能也不會生效。因?yàn)閁serService類沒有使用@Service、@Component或者@Controller等注解聲明,該類不會被Spring管理,因此也就無法使用Spring的異步功能。

8 自己new的對象

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

但如果new了一個Service類的對象,可能會出現(xià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了一個UserService類的對象,然后調(diào)用該對象的async()方法。

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

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

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

9 Spring無法掃描異步類

我們在Spring項(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這個路徑是不存在的,會導(dǎo)致@Async注解異步的功能失效。

同時如果@ComponentScan注解定義的路徑,沒有包含你新加的Servcie類的路徑,@Async注解異步的功能也會失效。

好了,今天的文章內(nèi)容先到這里。

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2024-06-18 08:37:25

場景異步編程代碼

2021-04-14 15:17:08

Transaction代碼語言

2023-09-28 09:07:54

注解失效場景

2020-04-14 13:32:56

@Transacti失效場景

2024-04-19 13:57:30

索引數(shù)據(jù)庫查詢

2024-09-09 08:29:25

2025-02-10 00:27:54

2022-01-09 18:32:03

MySQL SQL 語句數(shù)據(jù)庫

2021-09-04 07:56:44

Spring事務(wù)失效

2021-08-04 00:10:49

場景版本大文件

2023-07-05 08:45:18

Spring事務(wù)失效場景

2022-05-26 08:23:05

MySQL索引數(shù)據(jù)庫

2022-02-14 16:53:57

Spring項(xiàng)目數(shù)據(jù)庫

2024-05-08 08:18:05

索引失效場景

2024-12-17 00:00:00

Spring線程

2024-07-12 14:46:20

2024-06-19 19:17:04

2022-08-29 09:06:43

hippo4j動態(tài)線程池

2012-08-20 15:14:23

2020-10-09 06:52:31

設(shè)計模式軟件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號