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

Java設(shè)計(jì)模式之代理模式與@Async異步注解失效的解決

 更新時(shí)間:2022年07月27日 09:34:43   作者:kaico2018  
代理模式是Java常見(jiàn)的設(shè)計(jì)模式之一。所謂代理模式是指客戶(hù)端并不直接調(diào)用實(shí)際的對(duì)象,而是通過(guò)調(diào)用代理,來(lái)間接的調(diào)用實(shí)際的對(duì)象

自定義注解實(shí)現(xiàn)方式

JDK動(dòng)態(tài)代理實(shí)現(xiàn)自定義異步注解(@Async)

實(shí)現(xiàn)思路:

  • 首先自定義一個(gè)注解,命名為:ExtAsync
  • 實(shí)現(xiàn)一個(gè)接口,這個(gè)接口的實(shí)現(xiàn)類(lèi)就是被代理類(lèi)
  • 實(shí)現(xiàn)jdk的InvocationHandler接口,根據(jù)反射獲取目標(biāo)方法的信息,判斷是否有異步注解,如果有則另起一個(gè)線程異步執(zhí)行去。

1、異步注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExtAsync {
}

2、接口和實(shí)現(xiàn)類(lèi)

//接口
public interface OrderService {
    String addOrder();
    void addOrderLog();
}
//實(shí)現(xiàn)類(lèi)
public class OrderServiceImpl implements OrderService {
    private OrderService orderServiceProxy;
    public String addOrder() {
        System.out.println(Thread.currentThread().getName() + ">>>流程1");
        orderServiceProxy.addOrderLog();
        System.out.println(Thread.currentThread().getName() + ">>>流程3");
        return "addOrder";
    }
    @ExtAsync
    public void addOrderLog() {
        System.out.println(Thread.currentThread().getName() + ">>>流程2");
    }
    public void setOrderServiceProxy(OrderService orderServiceProxy) {
        this.orderServiceProxy = orderServiceProxy;
    }
}

3、JDK動(dòng)態(tài)代理需要實(shí)現(xiàn)的InvocationHandler接口類(lèi)

public class MayiktInvocationHandler implements InvocationHandler {
    /**
     * 目標(biāo)對(duì)象
     */
    private Object target;
    /**
     * 定義線程池
     */
    private ExecutorService executorService;
    public MayiktInvocationHandler(Object target) {
        this.target = target;
        executorService = Executors.newFixedThreadPool(10);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //使用反射技術(shù)執(zhí)行目標(biāo)方法
//        ExtAsync extAsync = method.getDeclaredAnnotation(ExtAsync.class);
        //根據(jù)接口的信息查找到目標(biāo)對(duì)象的的方法
        Method methodImpl = target.getClass().getMethod(method.getName(), method.getParameterTypes());
        ExtAsync extAsync = methodImpl.getDeclaredAnnotation(ExtAsync.class);
        if (extAsync == null) {
            // 該方法上沒(méi)有加上異步注解,則直接調(diào)用目標(biāo)方法
            return method.invoke(target, args);
        }
        // 單獨(dú)開(kāi)啟一個(gè)線程異步處理目標(biāo)方法
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    method.invoke(target, args);
                } catch (Exception e) {
                }
            }
        });
        return null;
    }
    /**
     * 生成代理類(lèi)
     *
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

4、測(cè)試類(lèi)

public class Test001 {
    public static void main(String[] args) {
        OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
        MayiktInvocationHandler mayiktInvocationHandler =
                new MayiktInvocationHandler(orderServiceImpl);
        // 使用Jdk生成代理對(duì)象
        OrderService orderServiceProxy = mayiktInvocationHandler.getProxy();
        // 將代理設(shè)置給目標(biāo)對(duì)象
        orderServiceImpl.setOrderServiceProxy(orderServiceProxy);
        orderServiceProxy.addOrder();
    }
}

總結(jié)分析:加上自定義的異步注解,查看輸出的日志順序,然后注釋掉異步注解,再看輸出的日志順序。

SpringAOP實(shí)現(xiàn)自定義異步注解

核心在于AOP切面類(lèi)上:攔截加了自定義異步注解的方法,看起一個(gè)線程執(zhí)行目標(biāo)方法。

@Component
@Aspect
@Slf4j
public class ExtAsyncAop {
    private ExecutorService executorService;
    public ExtAsyncAop() {
        executorService = Executors.newFixedThreadPool(10);
    }
    @Around(value = "@annotation(com.kaico.designMode.proxy.aopAsync.ext.ExtAsync)")
    public void doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
        // 直接獲取到方法上有加上ExtAsync
        log.info(">>>攔截到我們方法上有加上ExtAsync");
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                // 執(zhí)行我們的目標(biāo)方法
                try {
                    joinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        });
    }
}

Spring的異步注解@Async失效分析

注解原理:AOP技術(shù)–》動(dòng)態(tài)代理技術(shù)

Spring中是如何綜合使用Cglib和Jdk動(dòng)態(tài)代理呢?

  • 如果被代理類(lèi)有實(shí)現(xiàn)接口的情況下默認(rèn)采用 Jdk動(dòng)態(tài)代理 可以轉(zhuǎn)換為Cglib
  • 如果被代理類(lèi)沒(méi)有實(shí)現(xiàn)接口的情況下采用Cglib

異步注解失效:

1、如果控制類(lèi)(加了@RestController的類(lèi))中的有方法加上了異步注解,并且有實(shí)現(xiàn)接口的情況下,則采用JDK動(dòng)態(tài)代理,控制類(lèi)沒(méi)有注冊(cè)到SpringMVC容器中。

2、如果控制類(lèi)(加了@RestController的類(lèi))中有的方法加上了異步注解,但是沒(méi)有實(shí)現(xiàn)接口的情況下,則采用CGLIB動(dòng)態(tài)代理,控制類(lèi)可以注冊(cè)到SpringMVC容器,但是異步注解會(huì)失效。

為什么失效?

底層使用動(dòng)態(tài)代理模式,在代理類(lèi)創(chuàng)建線程,如果沒(méi)有經(jīng)過(guò)代理類(lèi)就不會(huì)創(chuàng)建線程,所以必須從Sping中獲取代理對(duì)象,通過(guò)代理對(duì)象.方法,才會(huì)經(jīng)過(guò)代理類(lèi)實(shí)現(xiàn)創(chuàng)建線程異步操作。因?yàn)樵诳刂祁?lèi)的方法增加異步注解的時(shí)候,調(diào)用該方法時(shí)調(diào)用的不是代理對(duì)象的方法,而是當(dāng)前對(duì)象的方法。

1、不要在當(dāng)前類(lèi)直接使用異步注解,因?yàn)闆](méi)有經(jīng)歷過(guò)代理類(lèi)。

2、官方建議新建一個(gè)類(lèi)來(lái)進(jìn)行異步操作。

原理: 如果在控制類(lèi)(實(shí)現(xiàn)接口的類(lèi))上的方法上加了異步注解,采用JDK動(dòng)態(tài)代理技術(shù),代理基于接口實(shí)現(xiàn),而接口中沒(méi)有加上@RestController注解,所以代理對(duì)象無(wú)法注冊(cè)到SpringMVC容器中。反之,如果控制類(lèi)沒(méi)有實(shí)現(xiàn)接口,則采用CGLIB動(dòng)態(tài)代理,生成的代理對(duì)象是采用繼承目標(biāo)對(duì)象(@RestController也會(huì)繼承過(guò)來(lái)),這時(shí)代理對(duì)象可以注入帶SpringMVC容器中。

到此這篇關(guān)于Java設(shè)計(jì)模式之代理模式與@Async異步注解失效的解決的文章就介紹到這了,更多相關(guān)Java代理模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC 重新定向redirect請(qǐng)求中攜帶數(shù)據(jù)方式

    SpringMVC 重新定向redirect請(qǐng)求中攜帶數(shù)據(jù)方式

    這篇文章主要介紹了SpringMVC 重新定向redirect請(qǐng)求中攜帶數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • nexus安裝及配置圖文教程

    nexus安裝及配置圖文教程

    Nexus 是Maven倉(cāng)庫(kù)管理器,通過(guò)nexus可以搭建maven倉(cāng)庫(kù),同時(shí)nexus還提供強(qiáng)大的倉(cāng)庫(kù)管理功能,構(gòu)件搜索功能等,文中有非常詳細(xì)的圖文介紹,對(duì)小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • 一文詳解java如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

    一文詳解java如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

    從?Java?8?開(kāi)始,便引入了一種稱(chēng)為“流式?API”的編程風(fēng)格,當(dāng)然也被稱(chēng)為“鏈?zhǔn)皆O(shè)置”或“鏈?zhǔn)秸{(diào)用”,本文主要來(lái)和大家討論一下如何實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,感興趣的可以了解下
    2023-12-12
  • 如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能

    如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能

    人工智能時(shí)代的到來(lái),相信大家已耳濡目染,虹軟免費(fèi),離線開(kāi)放的人臉識(shí)別SDK,正推動(dòng)著全行業(yè)進(jìn)入刷臉時(shí)代,下面這篇文章主要給大家介紹了關(guān)于如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • 詳解SpringBoot定時(shí)任務(wù)功能

    詳解SpringBoot定時(shí)任務(wù)功能

    這篇文章主要介紹了SpringBoot定時(shí)任務(wù)功能詳細(xì)解析,這次的功能開(kāi)發(fā)過(guò)程中也算是對(duì)其內(nèi)涵的進(jìn)一步了解,以后遇到定時(shí)任務(wù)的處理也更清晰,更有效率了,對(duì)SpringBoot定時(shí)任務(wù)相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-05-05
  • Spring自動(dòng)裝配之方法、構(gòu)造器位置的自動(dòng)注入操作

    Spring自動(dòng)裝配之方法、構(gòu)造器位置的自動(dòng)注入操作

    這篇文章主要介紹了Spring自動(dòng)裝配之方法、構(gòu)造器位置的自動(dòng)注入操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java中@ModelAttribute注解的作用

    java中@ModelAttribute注解的作用

    本文主要介紹了java中@ModelAttribute注解的作用。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • 使用JMF實(shí)現(xiàn)java視頻播放器

    使用JMF實(shí)現(xiàn)java視頻播放器

    這篇文章主要為大家詳細(xì)介紹了使用JMF實(shí)現(xiàn)java視頻播放器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 排序算法圖解之Java希爾排序

    排序算法圖解之Java希爾排序

    希爾排序是希爾(Donald?Shell)于1959年提出的一種排序算法,其也是一種特殊的插入排序,即將簡(jiǎn)單的插入排序進(jìn)行改進(jìn)后的一個(gè)更加高效的版本,也稱(chēng)縮小增量排序。本文通過(guò)圖片和示例講解了希爾排序的實(shí)現(xiàn),需要的可以了解一下
    2022-11-11
  • JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式

    JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式

    這篇文章主要介紹了JavaWeb?使用DBUtils實(shí)現(xiàn)增刪改查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評(píng)論