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

@Transaction,@Async在同一個(gè)類中注解失效的原因分析及解決

 更新時(shí)間:2021年12月28日 14:43:36   作者:baisq2017  
這篇文章主要介紹了@Transaction,@Async在同一個(gè)類中注解失效的原因分析及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

@Transaction @Async在同一個(gè)類中注解失效

在同一個(gè)類中,一個(gè)方法調(diào)用另外一個(gè)有注解(比如@Async,@Transational)的方法,注解是不會(huì)生效的。

比如,下面代碼例子中,有兩方法,一個(gè)有@Async注解,一個(gè)沒有。第一次如果調(diào)用了有注解的test()方法,會(huì)啟動(dòng)@Async注解作用;第一次如果調(diào)用testAsync(),因?yàn)樗鼉?nèi)部調(diào)用了有注解的test(),如果你以為系統(tǒng)也會(huì)為它啟動(dòng)Async作用,那就錯(cuò)了,實(shí)際上是沒有的。

@Service
public class TestAsyncService {
  public void testAsync() throws Exception {
    test();
  }
  @Async
  public void test() throws InterruptedException{
    Thread.sleep(10000);//讓線程休眠,根據(jù)輸出結(jié)果判斷主線程和從線程是同步還是異步
    System.out.println("異步threadId:"+Thread.currentThread().getId());
  }
}

運(yùn)行結(jié)果:testAsync()主線程和從線程()test()從線程同步執(zhí)行。

原因:spring 在掃描bean的時(shí)候會(huì)掃描方法上是否包含@Async注解,如果包含,spring會(huì)為這個(gè)bean動(dòng)態(tài)地生成一個(gè)子類(即代理類,proxy),代理類是繼承原來那個(gè)bean的。

此時(shí),當(dāng)這個(gè)有注解的方法被調(diào)用的時(shí)候,實(shí)際上是由代理類來調(diào)用的,代理類在調(diào)用時(shí)增加異步作用。

然而,如果這個(gè)有注解的方法是被同一個(gè)類中的其他方法調(diào)用的,那么該方法的調(diào)用并沒有通過代理類,而是直接通過原來的那個(gè)bean,所以就沒有增加異步作用,我們看到的現(xiàn)象就是@Async注解無(wú)效。

下面用偽代碼闡述一下原因

@Service  
class A{  
    @Async
    method b(){...}  
    method a(){    //標(biāo)記1  
        b();  
    }  
}  
//Spring掃描注解后,創(chuàng)建了另外一個(gè)代理類,并為有注解的方法加上異步效果  
class proxy$A{  
    A objectA = new A();  
    method b(){    //標(biāo)記2  
        //異步執(zhí)行Async  
        objectA.b();  
    }  
    method a(){    //標(biāo)記3  
        objectA.a();    //由于a()沒有注解,所以不會(huì)異步執(zhí)行,而是直接調(diào)用A的實(shí)例的a()方法  
    }  
}  

當(dāng)我們調(diào)用A的bean的a()方法的時(shí)候,也是被proxyA攔截,執(zhí)行proxyA攔截,執(zhí)行proxyA.a()(標(biāo)記3),然而,由以上代碼可知,這時(shí)候它調(diào)用的是objectA.a(),也就是由原來的bean來調(diào)用a()方法了,所以代碼跑到了“標(biāo)記1”。由此可見,“標(biāo)記2”并沒有被執(zhí)行到,所以異步執(zhí)行的效果也沒有運(yùn)行。

說說解決

了解了失效的原因,解決的方法就簡(jiǎn)單了(兩種):

  • 把這兩個(gè)方法分開到不同的類中
  • 把注解加到類名上面

@Async的實(shí)現(xiàn)類方式

詳解:用于開啟異步處理的接口, @Async,使用異步必須再啟動(dòng)類加上@EnableAsync

方法1:實(shí)現(xiàn)接口AsyncConfigurer

@Configuration
public class ThreadConfiguration implements AsyncConfigurer {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    @Bean
    public Executor getAsyncExecutor() {
        executor.setThreadNamePrefix("Zy-TaskExecutor-");
        executor.setCorePoolSize(50);// 核心線程池大小
        executor.setMaxPoolSize(200);// 最大可創(chuàng)建的線程數(shù)
        executor.setQueueCapacity(1000);// 隊(duì)列最大長(zhǎng)度
        executor.setKeepAliveSeconds(300);// 線程池維護(hù)線程所允許的空閑時(shí)間
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        logger.info("任務(wù)線程池初始化...");
        return executor;
    }
    /**
     * 只有在方法上添加@Async的出現(xiàn)異常才會(huì)跳到此方法中
     * */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        logger.error("線程執(zhí)行出現(xiàn)異常....");
        return (e, method, arguments) -> logger.error("exception method : " + method.getName() + " message:" + e.getMessage(), e);
    }
    /**
     * 線程監(jiān)控類,訪問/monitor
     * */
    @Bean
    public ServletRegistrationBean threadPoolMonitorServlet() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new HttpServlet() {
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                PrintWriter writer = resp.getWriter();
                writer.print("corePoolSize : " + executor.getCorePoolSize());
                writer.flush();
                writer.close();
            }
        });
        registration.addUrlMappings("/monitor/*");
        logger.info("springboot線程監(jiān)控start!");
        return registration;
    }
}

方法2:直接注入bean

@Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(200);
        executor.setQueueCapacity(1000);
        executor.setCorePoolSize(50);
        executor.setKeepAliveSeconds(300);
        executor.setThreadNamePrefix("Zy-TaskExecutor-");
        // 線程池對(duì)拒絕任務(wù)(無(wú)線程可用)的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        log.info("任務(wù)線程池初始化...");
        return executor;
    }

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java HashMap的工作原理

    Java HashMap的工作原理

    這篇文章主要介紹了Java HashMap的工作原理的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • java中pdf轉(zhuǎn)圖片的實(shí)現(xiàn)方法

    java中pdf轉(zhuǎn)圖片的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava中pdf轉(zhuǎn)圖片的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • SpringBoot啟動(dòng)過程逐步分析講解

    SpringBoot啟動(dòng)過程逐步分析講解

    這篇文章主要介紹了SpringBoot啟動(dòng)過程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01
  • Spring?Bean后處理器詳細(xì)介紹

    Spring?Bean后處理器詳細(xì)介紹

    Bean后置處理器允許在調(diào)用初始化方法前后對(duì)Bean進(jìn)行額外的處理。可以在?Spring容器通過插入一個(gè)或多個(gè)BeanPostProcessor的實(shí)現(xiàn)來完成實(shí)例化,配置和初始化一個(gè)?bean?之后實(shí)現(xiàn)一些自定義邏輯回調(diào)方法
    2023-01-01
  • Mybatis 中Mapper使用package方式配置報(bào)錯(cuò)的解決方案

    Mybatis 中Mapper使用package方式配置報(bào)錯(cuò)的解決方案

    這篇文章主要介紹了Mybatis 中Mapper使用package方式配置報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中Volatile關(guān)鍵字能保證原子性嗎

    Java中Volatile關(guān)鍵字能保證原子性嗎

    這篇文章主要介紹了Java中Volatile關(guān)鍵字能保證原子性嗎,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)

    本文主要介紹了Java批量獲取地址間距離,獲取兩個(gè)地址間距離,實(shí)現(xiàn)方式比較多,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 詳解如何在低版本的Spring中快速實(shí)現(xiàn)類似自動(dòng)配置的功能

    詳解如何在低版本的Spring中快速實(shí)現(xiàn)類似自動(dòng)配置的功能

    這篇文章主要介紹了詳解如何在低版本的Spring中快速實(shí)現(xiàn)類似自動(dòng)配置的功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-05-05
  • Spring boot如何集成kaptcha并生成驗(yàn)證碼

    Spring boot如何集成kaptcha并生成驗(yàn)證碼

    這篇文章主要介紹了Spring boot如何集成kaptcha并生成驗(yàn)證碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java中檢查值是否存在于數(shù)組中的4種詳細(xì)方法

    Java中檢查值是否存在于數(shù)組中的4種詳細(xì)方法

    這篇文章主要給大家介紹了關(guān)于Java中檢查值是否存在于數(shù)組中的4種詳細(xì)方法,相信大家在操作Java的時(shí)候經(jīng)常會(huì)要檢查一個(gè)數(shù)組(無(wú)序)是否包含一個(gè)特定的值,需要的朋友可以參考下
    2023-08-08

最新評(píng)論