国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

這篇具有很好參考價(jià)值的文章主要介紹了quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

歡迎訪問我的GitHub

這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos

本篇概覽

  • 本篇是《quarkus依賴注入》系列的終篇,前面十二篇已覆蓋quarkus依賴注入的大部分核心內(nèi)容,但依然漏掉了一些知識(shí)點(diǎn),今天就將剩下的內(nèi)容匯總,來個(gè)一鍋端,輕松愉快的結(jié)束這個(gè)系列
  • 總的來說,本篇由以下內(nèi)容構(gòu)成,每個(gè)段落都是個(gè)獨(dú)立的知識(shí)點(diǎn)
  1. 幾處可以簡(jiǎn)化編碼的地方,如bean注入、構(gòu)造方法等
  2. WithCaching:特定場(chǎng)景下,減少bean實(shí)例化次數(shù)
  3. 靜態(tài)方法是否可以被攔截器攔截?
  4. All注解,讓多個(gè)bean的注入更加直觀
  5. 統(tǒng)一處理異步事件的異常
  • 咱們從最簡(jiǎn)單的看起:表達(dá)方式的簡(jiǎn)化,一共有三個(gè)位置可以簡(jiǎn)化:bean的注入、bean構(gòu)造方法、bean生產(chǎn)方法

簡(jiǎn)化之一:bean注入

  • quarkus在CDI規(guī)范的基礎(chǔ)上做了簡(jiǎn)化,可以讓我們少寫幾行代碼

  • 將配置文件中名為greeting.message的配置項(xiàng)注入到bean的成員變量greetingMsg中,按照CDI規(guī)范的寫法如下

  @Inject
  @ConfigProperty(name = "greeting.message")
  String greetingMsg;
  • 在quarkus框架下可以略去@Inject,寫成下面這樣的效果和上面的代碼一模一樣
@ConfigProperty(name = "greeting.message")
String greetingMsg;

簡(jiǎn)化之二:bean構(gòu)造方法

  • 關(guān)于bean的構(gòu)造方法,CDI有兩個(gè)規(guī)定:首先,必須要有無參構(gòu)造方法,其次,有參數(shù)的構(gòu)造方法需要@Inject注解修飾,實(shí)例代碼如下所示
@ApplicationScoped
public class MyCoolService {

  private SimpleProcessor processor;

  MyCoolService() { // dummy constructor needed
  }

  @Inject // constructor injection
  MyCoolService(SimpleProcessor processor) {
    this.processor = processor;
  }
}
  • 但是,在quarkus框架下,無參構(gòu)造方法可不寫,有參數(shù)的構(gòu)造方法也可以略去@Inject,寫成下面這樣的效果和上面的代碼一模一樣
@ApplicationScoped
public class MyCoolService {

  private SimpleProcessor processor;

  MyCoolService(SimpleProcessor processor) {
    this.processor = processor;
  }
}

簡(jiǎn)化之三:bean生產(chǎn)方法

  • 在CDI規(guī)范中,通過方法生產(chǎn)bean的語法如下,可見要同時(shí)使用ProducesApplicationScoped注解修飾返回bean的方法
class Producers {
  
  @Produces
  @ApplicationScoped
  MyService produceServ
    ice() {
    return new MyService(coolProperty);
  }
}
  • 在quarkus框架下可以略去@Produces,寫成下面這樣的效果和上面的代碼一模一樣
class Producers {

  @ApplicationScoped
  MyService produceService() {
    return new MyService(coolProperty);
  }
}
  • 好了,熱身結(jié)束,接下來看幾個(gè)略有深度的技能

WithCaching注解:避免不必要的多次實(shí)例化

  • 在介紹WithCaching注解之前,先來看一個(gè)普通場(chǎng)景
  • 下面是一段單元測(cè)試代碼,HelloDependent類型的bean通過Instance的方式被注入,再用Instance#get來獲取此bean
@QuarkusTest
public class WithCachingTest {

    @Inject
    Instance<HelloDependent> instance;

    @Test
    public void test() {
        // 第一次調(diào)用Instance#get方法
        HelloDependent helloDependent = instance.get();
        helloDependent.hello();

        // 第二次調(diào)用Instance#get方法
        helloDependent = instance.get();
        helloDependent.hello();
    }
}
  • 上述代碼是種常見的bean注入和使用方式,我們的本意是在WithCachingTest實(shí)例中多次使用HelloDependent類型的bean,可能是在test方法中使用,也可能在WithCachingTest的其他方法中使用

  • 如果HelloDependent的作用域是ApplicationScoped,上述代碼一切正常,但是,如果作用域是Dependent呢?代碼中執(zhí)行了兩次Instance#get,得到的HelloDependent實(shí)例是同一個(gè)嗎?Dependent的特性是每次注入都實(shí)例化一次,這里的Instance#get又算幾次注入呢?

  • 最簡(jiǎn)單的方法就是運(yùn)行上述代碼看實(shí)際效果,這里先回顧HelloDependent.java的源碼,如下所示,構(gòu)造方法中會(huì)打印日志,這下好辦了,只要看日志出現(xiàn)幾次,就知道實(shí)例化幾次了

@Dependent
public class HelloDependent {

    public HelloDependent(InjectionPoint injectionPoint) {
        Log.info("injecting from bean "+ injectionPoint.getMember().getDeclaringClass());
    }

    public String hello() {
        return this.getClass().getSimpleName();
    }
}
  • 運(yùn)行單元測(cè)試類WithCachingTest,如下圖紅框所示,構(gòu)造方法中的日志打印了兩次,所以:每次Instance#get都相當(dāng)于一次注入,如果bean的作用域是Dependent,就會(huì)創(chuàng)建一個(gè)新的實(shí)例并返回
quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)
  • 現(xiàn)在問題來了:如果bean的作用域必須是Dependent,又希望多次Instance#get返回的是同一個(gè)bean實(shí)例,這樣的要求可以做到嗎?
  • 答案是可以,用WithCaching注解修飾Instance即可,改動(dòng)如下圖紅框1,改好后再次運(yùn)行,紅框2顯示HelloDependent只實(shí)例化了一次

quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

攔截靜態(tài)方法

  • 先回顧一下攔截器的基本知識(shí),定義一個(gè)攔截器并用來攔截bean中的方法,總共需要完成以下三步
quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)
  • 實(shí)現(xiàn)攔截器的具體功能時(shí),還要用注解指明攔截器類型,一共有四種類型
  1. AroundInvoke:攔截bean方法
  2. PostConstruct:生命周期攔截器,bean創(chuàng)建后執(zhí)行
  3. PreDestroy:生命周期攔截器,bean銷毀前執(zhí)行
  4. AroundConstruct:生命周期攔截器,攔截bean構(gòu)造方法
  • 現(xiàn)在問題來了:攔截器能攔截靜態(tài)方法嗎?
  • 答案是可以,但是有限制,具體的限制如下
  1. 僅支持方法級(jí)別的攔截(即攔截器修飾的是方法)
  2. private型的靜態(tài)方法不會(huì)被攔截
  3. 下圖是攔截器實(shí)現(xiàn)的常見代碼,通過入?yún)?font color="blue">InvocationContext的getTarget方法,可以得到被攔截的對(duì)象,然而,在攔截靜態(tài)方法時(shí),getTarget方法的返回值是null,這一點(diǎn)尤其要注意,例如下圖紅框中的代碼,在攔截靜態(tài)方法是就會(huì)拋出空指針異常
quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

All更加直觀的注入

  • 假設(shè)有個(gè)名為SayHello的接口,源碼如下
public interface SayHello {
    void hello();
}
  • 現(xiàn)在有三個(gè)bean都實(shí)現(xiàn)了SayHello接口,如果想要調(diào)用這三個(gè)bean的hello方法,應(yīng)該怎么做呢?

  • 按照CDI的規(guī)范,應(yīng)該用Instance注入,然后使用Instance中的迭代器即可獲取所有bean,代碼如下

public class InjectAllTest {
    /**
     * 用Instance接收注入,得到所有SayHello類型的bean
     */
    @Inject
    Instance<SayHello> instance;

    @Test
    public void testInstance() {
        // instance中有迭代器,可以用遍歷的方式得到所有bean
        for (SayHello sayHello : instance) {
            sayHello.hello();
        }
    }
}
  • quarkus提供了另一種方式,借助注解io.quarkus.arc.All,可以將所有SayHello類型的bean注入到List中,如下所示
@QuarkusTest
public class InjectAllTest {
    /**
     * 用All注解可以將SayHello類型的bean全部注入到list中,
     * 這樣更加直觀
     */
    @All
    List<SayHello> list;

    @Test
    public void testAll() {
        for (SayHello sayHello : list) {
            sayHello.hello();
        }
    }
}
  • 和CDI規(guī)范相比,使用All注解可以讓代碼顯得更為直觀,另外還有以下三個(gè)特點(diǎn)
  1. 此list是immutable的(內(nèi)容不可變)

  2. list中的bean是按照priority排序的

  3. 如果您需要的不僅僅是注入bean,還需要bean的元數(shù)據(jù)信息(例如bean的scope),可以將List中的類型從SayHello改為InstanceHandle<SayHello>,這樣即可以得到注入bean,也能得到注入bean的元數(shù)據(jù)(在InjectableBean中),參考代碼如下

@QuarkusTest
public class InjectAllTest {
    
    @All
    List<InstanceHandle<SayHello>> list;

    @Test
    public void testQuarkusAllAnnonation() {
        for (InstanceHandle<SayHello> instanceHandle : list) {
            // InstanceHandle#get可以得到注入bean
            SayHello sayHello = instanceHandle.get();

            // InjectableBean封裝了注入bean的元數(shù)據(jù)信息
            InjectableBean<SayHello> injectableBean = instanceHandle.getBean();

            // 例如bean的作用域就能從InjectableBean中取得
            Class clazz = injectableBean.getScope();

            // 打印出來驗(yàn)證
            Log.infov("bean [{0}], scope [{1}]", sayHello.getClass().getSimpleName(), clazz.getSimpleName() );
        }
    }
}
  • 代碼的執(zhí)行結(jié)果如下圖紅框所示,可見注入bean及其作用域都能成功取得(要注意的是注入bean是代理bean)

quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

統(tǒng)一處理異步事件的異常

  • 需要提前說一下,本段落涉及的知識(shí)點(diǎn)和AsyncObserverExceptionHandler類有關(guān),而《quarkus依賴注入》系列所用的quarkus-2.7.3.Final版本中并沒有AsyncObserverExceptionHandler類,后來將quarkus版本更新為2.8.2.Final,就可以正常使用AsyncObserverExceptionHandler類了

  • 本段落的知識(shí)點(diǎn)和異步事件有關(guān):如果消費(fèi)異步事件的過程中發(fā)生異常,而開發(fā)者有沒有專門寫代碼處理異步消費(fèi)結(jié)果,那么此異常就默默無聞的被忽略了,我們也可能因此錯(cuò)失了及時(shí)發(fā)現(xiàn)和處理問題的時(shí)機(jī)

  • 來寫一段代碼復(fù)現(xiàn)上述問題,首先是事件定義TestEvent.java,就是個(gè)普通類,啥都沒有

public class TestEvent {
}
  • 然后是事件的生產(chǎn)者TestEventProducer.java,注意其調(diào)用fireAsync方法發(fā)送了一個(gè)異步事件
@ApplicationScoped
public class TestEventProducer {

    @Inject
    Event<TestEvent> event;

    /**
     * 發(fā)送異步事件
     */
    public void asyncProduce() {
        event.fireAsync(new TestEvent());
    }
}
  • 事件的消費(fèi)者TestEventConsumer.java,這里在消費(fèi)TestEvent事件的時(shí)候,故意拋出了異常
@ApplicationScoped
public class TestEventConsumer {

    /**
     * 消費(fèi)異步事件,這里故意拋出異常
     */
    public void aSyncConsume(@ObservesAsync TestEvent testEvent) throws Exception {
       throw new Exception("exception from aSyncConsume");
    }
}
  • 最后是單元測(cè)試類將事件的生產(chǎn)和消費(fèi)運(yùn)行起來
@QuarkusTest
public class EventExceptionHandlerTest {

    @Inject
    TestEventProducer testEventProducer;

    @Test
    public void testAsync() throws InterruptedException {
       testEventProducer.asyncProduce();
    }
}
  • 運(yùn)行EventExceptionHandlerTest,結(jié)果如下圖,DefaultAsyncObserverExceptionHandler處理了這個(gè)異常,這是quarkus框架的默認(rèn)處理邏輯

quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

  • DefaultAsyncObserverExceptionHandler只是輸出了日志,這樣的處理對(duì)于真實(shí)業(yè)務(wù)是不夠的(可能需要記錄到特定地方,調(diào)用其他告警服務(wù)等),所以,我們需要自定義默認(rèn)的異步事件異常處理器
  • 自定義的全局異步事件異常處理器如下
package com.bolingcavalry.service.impl;

import io.quarkus.arc.AsyncObserverExceptionHandler;
import io.quarkus.logging.Log;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.spi.EventContext;
import javax.enterprise.inject.spi.ObserverMethod;

@ApplicationScoped
public class NoopAsyncObserverExceptionHandler implements AsyncObserverExceptionHandler {

    @Override
    public void handle(Throwable throwable, ObserverMethod<?> observerMethod, EventContext<?> eventContext) {
        // 異常信息
        Log.info("exception is - " + throwable);
        // 事件信息
        Log.info("observer type is - " + observerMethod.getObservedType().getTypeName());
    }
}
  • 此刻,咱們?cè)賵?zhí)行一次單元測(cè)試,如下圖所示,異常已經(jīng)被NoopAsyncObserverExceptionHandler#handler處理,異常和事件相關(guān)的信息都能拿到,您可以按照實(shí)際的業(yè)務(wù)需求來進(jìn)行定制了

quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

  • 另外還要說明一下,自定義的全局異步事件異常處理器,其作用域只能是ApplicationScoped或者Singleton
  • 至此,《quarkus依賴注入》系列全部完成,與bean相關(guān)的故事也就此結(jié)束了,十三篇文章凝聚了欣宸對(duì)quarkus框架bean容器的思考和實(shí)踐,希望能幫助您更快的掌握和理解quarkus最核心的領(lǐng)域
  • 雖然《quarkus依賴注入》已經(jīng)終結(jié),但是《quarkus實(shí)戰(zhàn)》系列依然還在持續(xù)更新中,有了依賴注入的知識(shí)作為基礎(chǔ),接下來的quarkus之旅會(huì)更加輕松和高效

歡迎關(guān)注博客園:程序員欣宸

學(xué)習(xí)路上,你不孤單,欣宸原創(chuàng)一路相伴...文章來源地址http://www.zghlxwxcb.cn/news/detail-642051.html

到了這里,關(guān)于quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • quarkus依賴注入之三:用注解選擇注入bean

    quarkus依賴注入之三:用注解選擇注入bean

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本文是《quarkus依賴注入》系列的第三篇,前文咱們掌握了創(chuàng)建bean的幾種方式,本篇趁熱打鐵,學(xué)習(xí)一個(gè)與創(chuàng)建bean有關(guān)的重要知識(shí)點(diǎn):一個(gè)接口如果有多個(gè)實(shí)現(xiàn)類時(shí),bean實(shí)例應(yīng)該如何選擇其中的一個(gè)

    2024年02月14日
    瀏覽(23)
  • quarkus依賴注入之七:生命周期回調(diào)

    quarkus依賴注入之七:生命周期回調(diào)

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇的知識(shí)點(diǎn)是bean的生命周期回調(diào):在bean生命周期的不同階段,都可以觸發(fā)自定義代碼的執(zhí)行 觸發(fā)自定義代碼執(zhí)行的具體方式,是用對(duì)應(yīng)的注解去修飾要執(zhí)行的方法,如下圖所示: 有兩種模式可以

    2024年02月14日
    瀏覽(23)
  • quarkus依賴注入之四:選擇注入bean的高級(jí)手段

    quarkus依賴注入之四:選擇注入bean的高級(jí)手段

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本文是《quarkus依賴注入》系列的第四篇,在應(yīng)用中,一個(gè)接口有多個(gè)實(shí)現(xiàn)是很常見的,那么依賴注入時(shí),如果類型是接口,如何準(zhǔn)確選擇實(shí)現(xiàn)呢?前文介紹了五種注解,用于通過配置項(xiàng)、profile等手

    2024年02月14日
    瀏覽(19)
  • quarkus依賴注入之六:發(fā)布和消費(fèi)事件

    quarkus依賴注入之六:發(fā)布和消費(fèi)事件

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本文是《quarkus依賴注入》系列的第六篇,主要內(nèi)容是學(xué)習(xí)事件的發(fā)布和接收 如果您用過Kafka、RabbitMQ等消息中間件,對(duì)消息的作用應(yīng)該不會(huì)陌生,通過消息的訂閱和發(fā)布可以降低系統(tǒng)之間的耦合性,

    2024年02月14日
    瀏覽(18)
  • quarkus依賴注入之八:裝飾器(Decorator)

    quarkus依賴注入之八:裝飾器(Decorator)

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》系列的第八篇,目標(biāo)是掌握quarkus實(shí)現(xiàn)的一個(gè)CDI特性:裝飾器(Decorator) 提到裝飾器,熟悉設(shè)計(jì)模式的讀者應(yīng)該會(huì)想到裝飾器模式,個(gè)人覺得下面這幅圖很好的解釋了裝飾器

    2024年02月14日
    瀏覽(45)
  • quarkus依賴注入之九:bean讀寫鎖

    quarkus依賴注入之九:bean讀寫鎖

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》的第九篇,目標(biāo)是在輕松的氣氛中學(xué)習(xí)一個(gè)小技能:bean鎖 quarkus的bean鎖本身很簡(jiǎn)單:用兩個(gè)注解修飾bean和方法即可,但涉及到多線程同步問題,欣宸愿意花更多篇幅與各位

    2024年02月14日
    瀏覽(25)
  • quarkus依賴注入之五:攔截器(Interceptor)

    quarkus依賴注入之五:攔截器(Interceptor)

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本文是《quarkus依賴注入》系列的第五篇,經(jīng)過前面的學(xué)習(xí),咱們熟悉了依賴注入的基本特性,接下來進(jìn)一步了解相關(guān)的高級(jí)特性,先從本篇的攔截器開始 如果您熟悉spring的話,對(duì)攔截器應(yīng)該不會(huì)陌

    2024年02月14日
    瀏覽(45)
  • quarkus依賴注入之二:bean的作用域

    quarkus依賴注入之二:bean的作用域

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 官方資料:https://lordofthejars.github.io/quarkus-cheat-sheet/#_injection 作為《quarkus依賴注入》系列的第二篇,繼續(xù)學(xué)習(xí)一個(gè)重要的知識(shí)點(diǎn):bean的作用域(scope),每個(gè)bean的作用域是唯一的,不同類型的作用域

    2024年02月15日
    瀏覽(16)
  • 軟件設(shè)計(jì)模式系列之十三——享元模式

    軟件設(shè)計(jì)模式系列之十三——享元模式

    享元模式(Flyweight Pattern)是一種結(jié)構(gòu)型設(shè)計(jì)模式,它旨在減少內(nèi)存占用或計(jì)算開銷,通過共享大量細(xì)粒度對(duì)象來提高系統(tǒng)的性能。這種模式適用于存在大量相似對(duì)象實(shí)例,但它們的狀態(tài)可以外部化(extrinsic),并且可以在多個(gè)對(duì)象之間共享的情況。 為了更好地理解享元模式

    2024年02月08日
    瀏覽(25)
  • JavaCV的攝像頭實(shí)戰(zhàn)之十三:年齡檢測(cè)

    JavaCV的攝像頭實(shí)戰(zhàn)之十三:年齡檢測(cè)

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本文是《JavaCV的攝像頭實(shí)戰(zhàn)》系列的第十三篇,前文《JavaCV的攝像頭實(shí)戰(zhàn)之十二:性別檢測(cè)》中,借助訓(xùn)練好的卷積神經(jīng)網(wǎng)絡(luò)模型開發(fā)出了識(shí)別性別的應(yīng)用,今天在前文基礎(chǔ)上做少量改動(dòng),實(shí)現(xiàn)年齡

    2024年02月11日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包