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

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

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

歡迎訪問我的GitHub

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

關(guān)于bean的作用域(scope)

  • 官方資料:https://lordofthejars.github.io/quarkus-cheat-sheet/#_injection

  • 作為《quarkus依賴注入》系列的第二篇,繼續(xù)學(xué)習(xí)一個(gè)重要的知識(shí)點(diǎn):bean的作用域(scope),每個(gè)bean的作用域是唯一的,不同類型的作用域,決定了各個(gè)bean實(shí)例的生命周期,例如:何時(shí)何處創(chuàng)建,又何時(shí)何處銷毀

  • bean的作用域在代碼中是什么樣的?回顧前文的代碼,如下,ApplicationScoped就是作用域,表明bean實(shí)例以單例模式一直存活(只要應(yīng)用還存活著),這是業(yè)務(wù)開發(fā)中常用的作用域類型:

@ApplicationScoped
public class ClassAnnotationBean {

    public String hello() {
        return "from " + this.getClass().getSimpleName();
    }
}
  • 作用域有多種,如果按來源區(qū)分一共兩大類:quarkus內(nèi)置和擴(kuò)展組件中定義,本篇聚焦quarkus的內(nèi)置作用域
  • 下面是整理好的作用域一覽,接下來會(huì)逐個(gè)講解
graph LR L1(作用域) --> L2-1(內(nèi)置) L1 --> L2-2(擴(kuò)展組件) L2-1 --> L3-1(常規(guī)作用域) L2-1 --> L3-2(偽作用域) L3-1 --> L4-1(ApplicationScoped) L3-1 --> L4-2(RequestScoped) L3-1 --> L4-3(SessionScoped) L3-2 --> L4-4(Singleton) L3-2 --> L4-5(Dependent) L2-2 --> L3-6(例如 : TransactionScoped)

常規(guī)作用域和偽作用域

  • 常規(guī)作用域,quarkus官方稱之為normal scope,包括:ApplicationScoped、RequestScoped、SessionScoped三種
  • 偽作用域稱之為pseudo scope,包括:Singleton、RequestScoped、Dependent兩種
  • 接下來,用一段最平常的代碼來揭示常規(guī)作用域和偽作用域的區(qū)別
  • 下面的代碼中,ClassAnnotationBean的作用域ApplicationScoped就是normal scope,如果換成Singleton就是pseudo scope
@ApplicationScoped
public class ClassAnnotationBean {

    public String hello() {
        return "from " + this.getClass().getSimpleName();
    }
}
  • 再來看使用ClassAnnotationBean的代碼,如下所示,是個(gè)再平常不過的依賴注入
@Path("/classannotataionbean")
public class ClassAnnotationController {

    @Inject
    ClassAnnotationBean classAnnotationBean;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String get() {
        return String.format("Hello RESTEasy, %s, %s",
                LocalDateTime.now(),
                classAnnotationBean.hello());
    }
}
  • 現(xiàn)在問題來了,ClassAnnotationBean是何時(shí)被實(shí)例化的?有以下兩種可能:
  1. 第一種:ClassAnnotationController被實(shí)例化的時(shí)候,classAnnotationBean會(huì)被注入,這時(shí)ClassAnnotationBean被實(shí)例化

  2. 第二種:get方法第一次被調(diào)用的時(shí)候,classAnnotationBean真正發(fā)揮作用,這時(shí)ClassAnnotationBean被實(shí)例化

  • 所以,一共有兩個(gè)時(shí)間點(diǎn):注入時(shí)和get方法首次執(zhí)行時(shí),作用域不同,這兩個(gè)時(shí)間點(diǎn)做的事情也不同,下面用表格來解釋
時(shí)間點(diǎn) 常規(guī)作用域 偽作用域
注入的時(shí)候 注入的是一個(gè)代理類,此時(shí)ClassAnnotationBean并未實(shí)例化 觸發(fā)ClassAnnotationBean實(shí)例化
get方法首次執(zhí)行的時(shí)候 1. 觸發(fā)ClassAnnotationBean實(shí)例化
2. 執(zhí)行常規(guī)業(yè)務(wù)代碼
1. 執(zhí)行常規(guī)業(yè)務(wù)代碼
  • 至此,您應(yīng)該明白兩種作用域的區(qū)別了:偽作用域的bean,在注入的時(shí)候?qū)嵗?,常?guī)作用域的bean,在注入的時(shí)候并未實(shí)例化,只有它的方法首次執(zhí)行的時(shí)候才會(huì)實(shí)例化,如下圖

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

  • 接下來細(xì)看每個(gè)作用域

ApplicationScoped

  • ApplicationScoped算是最常用的作用域了,它修飾的bean,在整個(gè)應(yīng)用中只有一個(gè)實(shí)例

RequestScoped

  • 這是與當(dāng)前http請(qǐng)求綁定的作用域,它修飾的bean,在每次http請(qǐng)求時(shí)都有一個(gè)全新實(shí)例,來寫一段代碼驗(yàn)證
  • 首先是bean類RequestScopeBean.java,注意作用域是RequestScoped,如下,在構(gòu)造方法中打印日志,這樣可以通過日志行數(shù)知道實(shí)例化次數(shù)
package com.bolingcavalry.service.impl;

import io.quarkus.logging.Log;
import javax.enterprise.context.RequestScoped;

@RequestScoped
public class RequestScopeBean {

    /**
     * 在構(gòu)造方法中打印日志,通過日志出現(xiàn)次數(shù)對(duì)應(yīng)著實(shí)例化次數(shù)
     */
    public RequestScopeBean() {
        Log.info("Instance of " + this.getClass().getSimpleName());
    }

    public String hello() {
        return "from " + this.getClass().getSimpleName();
    }
}
  • 然后是使用bean的代碼,是個(gè)普通的web服務(wù)類
package com.bolingcavalry;

import com.bolingcavalry.service.impl.RequestScopeBean;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.time.LocalDateTime;

@Path("/requestscope")
public class RequestScopeController {

    @Inject
    RequestScopeBean requestScopeBean;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String get() {
        return String.format("Hello RESTEasy, %s, %s",
                LocalDateTime.now(),
                requestScopeBean.hello());
    }
}
  • 最后是單元測(cè)試代碼RequestScopeControllerTest.java,要注意的是注解RepeatedTest,有了此注解,testGetEndpoint方法會(huì)重復(fù)執(zhí)行,次數(shù)是注解的value屬性值,這里是10次
package com.bolingcavalry;

import com.bolingcavalry.service.impl.RequestScopeBean;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;

@QuarkusTest
class RequestScopeControllerTest {

    @RepeatedTest(10)
    public void testGetEndpoint() {
        given()
                .when().get("/requestscope")
                .then()
                .statusCode(200)
                // 檢查body內(nèi)容,是否含有ClassAnnotationBean.hello方法返回的字符串
                .body(containsString("from " + RequestScopeBean.class.getSimpleName()));
    }
}
  • 由于單元測(cè)試中接口會(huì)調(diào)用10次,按照RequestScoped作用域的定義,RequestScopeBean會(huì)實(shí)例化10次,執(zhí)行單元測(cè)試試試吧
  • 執(zhí)行結(jié)果如下圖,紅框4顯示每次http請(qǐng)求都會(huì)觸發(fā)一次RequestScopeBean實(shí)例化,符合預(yù)期,另外還有意外收獲,稍后馬上就會(huì)提到

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

  • 另外,請(qǐng)重點(diǎn)關(guān)注藍(lán)框和藍(lán)色注釋文字,這是意外收獲,居然看到了代理類的日志,看樣子代理類是繼承了RequestScopeBean類,于是父類構(gòu)造方法中的日志代碼也執(zhí)行了,還把代理類的類名打印出來了
  • 從日志可以看出:10次http請(qǐng)求,bean的構(gòu)造方法執(zhí)行了10次,代理類的構(gòu)造方法只執(zhí)行了一次,這是個(gè)重要結(jié)論:bean類被多次實(shí)例化的時(shí)候,代理類不會(huì)多次實(shí)例化

SessionScoped

  • SessionScoped與RequestScoped類似,區(qū)別是范圍,RequestScoped是每次http請(qǐng)求做一次實(shí)例化,SessionScoped是每個(gè)http會(huì)話,以下場(chǎng)景都在session范圍內(nèi),共享同一個(gè)bean實(shí)例:
  1. servlet的service方法
  2. servlet filter的doFileter方法
  3. web容器調(diào)用HttpSessionListener、AsyncListener、ServletRequestListener等監(jiān)聽器

Singleton

  • 提到Singleton,聰明的您是否想到了單例模式,這個(gè)scope也是此意:它修飾的bean,在整個(gè)應(yīng)用中只有一個(gè)實(shí)例

  • Singleton和ApplicationScoped很像,它們修飾的bean,在整個(gè)應(yīng)用中都是只有一個(gè)實(shí)例,然而它們也是有區(qū)別的:ApplicationScoped修飾的bean有代理類包裹,Singleton修飾的bean沒有代理類

  • Singleton修飾的bean沒有代理類,所以在使用的時(shí)候,對(duì)bean的成員變量直接讀寫都沒有問題(safely),而ApplicationScoped修飾的bean,請(qǐng)不要直接讀寫其成員變量,比較拿都是代理的東西,而不是bean的類自己的成員變量

  • Singleton修飾的bean沒有代理類,所以實(shí)際使用中性能會(huì)略好(slightly better performance)

  • 在使用QuarkusMock類做單元測(cè)試的時(shí)候,不能對(duì)Singleton修飾的bean做mock,因?yàn)闆]有代理類去執(zhí)行相關(guān)操作

  • quarkus官方推薦使用的是ApplicationScoped

  • Singleton被quarkus劃分為偽作用域,此時(shí)再回頭品味下圖,您是否恍然大悟:成員變量classAnnotationBean如果是Singleton,是沒有代理類的,那就必須在@Inject位置實(shí)例化,否則,在get方法中classAnnotationBean就是null,會(huì)空指針異常的

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

  • 運(yùn)行代碼驗(yàn)證是否有代理類,找到剛才的RequestScopeBean.java,將作用域改成Singleton,運(yùn)行單元測(cè)試類RequestScopeControllerTest.java,結(jié)果如下圖紅框,只有RequestScopeBean自己構(gòu)造方法的日志
    quarkus依賴注入之二:bean的作用域

  • 再將作用域改成ApplicationScoped,如下圖藍(lán)框,代理類日志出現(xiàn)

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

Dependent

  • Dependent是個(gè)偽作用域,它的特點(diǎn)是:每個(gè)依賴注入點(diǎn)的對(duì)象實(shí)例都不同
  • 假設(shè)DependentClinetA和DependentClinetB都用@Inject注解注入了HelloDependent,那么DependentClinetA引用的HelloDependent對(duì)象,DependentClinetB引用的HelloDependent對(duì)象,是兩個(gè)實(shí)例,如下圖,兩個(gè)hello是不同的實(shí)例
quarkus依賴注入之二:bean的作用域

Dependent的特殊能力

  • Dependent的特點(diǎn)是每個(gè)注入點(diǎn)的bean實(shí)例都不同,針對(duì)這個(gè)特點(diǎn),quarkus提供了一個(gè)特殊能力:bean的實(shí)例中可以取得注入點(diǎn)的元數(shù)據(jù)
  • 對(duì)應(yīng)上圖的例子,就是HelloDependent的代碼中可以取得它的使用者:DependentClientA和DependentClientB的元數(shù)據(jù)
  • 寫代碼驗(yàn)證這個(gè)特殊能力
  • 首先是HelloDependent的定義,將作用域設(shè)置為Dependent,然后注意其構(gòu)造方法的參數(shù),這就是特殊能力所在,是個(gè)InjectionPoint類型的實(shí)例,這個(gè)參數(shù)在實(shí)例化的時(shí)候由quarkus容器注入,通過此參數(shù)即可得知使用HelloDependent的類的身份
@Dependent
public class HelloDependent {

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

    public String hello() {
        return this.getClass().getSimpleName();
    }
}

  • 然后是HelloDependent的使用類DependentClientA
@ApplicationScoped
public class DependentClientA {

    @Inject
    HelloDependent hello;

    public String doHello() {
        return hello.hello();
    }
}
  • DependentClientB的代碼和DependentClientA一模一樣,就不貼出來了

  • 最后寫個(gè)單元測(cè)試類驗(yàn)證HelloDependent的特殊能力

@QuarkusTest
public class DependentTest {

    @Inject
    DependentClientA dependentClientA;

    @Inject
    DependentClientB dependentClientB;

    @Test
    public void testSelectHelloInstanceA() {
        Class<HelloDependent> clazz = HelloDependent.class;

        Assertions.assertEquals(clazz.getSimpleName(), dependentClientA.doHello());
        Assertions.assertEquals(clazz.getSimpleName(), dependentClientB.doHello());
    }
}
  • 運(yùn)行單元測(cè)試,如下圖紅框,首先,HelloDependent的日志打印了兩次,證明的確實(shí)例化了兩個(gè)HelloDependent對(duì)象,其次日志的內(nèi)容也準(zhǔn)確的將注入點(diǎn)的類的信息打印出來

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

擴(kuò)展組件的作用域

  • quarkus的擴(kuò)展組件豐富多彩,自己也能按照官方指引制作,所以擴(kuò)展組件對(duì)應(yīng)的作用域也隨著組件的不同而各不相同,就不在此列舉了,就舉一個(gè)例子吧:quarkus-narayana-jta組件中定義了一個(gè)作用域javax.transaction.TransactionScoped,該作用域修飾的bean,每個(gè)事物對(duì)應(yīng)一個(gè)實(shí)例

  • 至此,quarkus作用域的了解和實(shí)戰(zhàn)已經(jīng)完成,這樣一來,不論是使用bean還是創(chuàng)建bean,都能按業(yè)務(wù)需要來準(zhǔn)確控制其生命周期了

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

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

到了這里,關(guān)于quarkus依賴注入之二:bean的作用域的文章就介紹完了。如果您還想了解更多內(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依賴注入之十:學(xué)習(xí)和改變bean懶加載規(guī)則

    quarkus依賴注入之十:學(xué)習(xí)和改變bean懶加載規(guī)則

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》系列的第十篇,來看一個(gè)容易被忽略的知識(shí)點(diǎn):bean的懶加載,咱們先去了解quarkus框架下的懶加載規(guī)則,然后更重要的是掌握如何改變規(guī)則,以達(dá)到提前實(shí)例化的目標(biāo) 總的來

    2024年02月14日
    瀏覽(25)
  • 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依賴注入之六:發(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依賴注入之五:攔截器(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依賴注入之十二:禁用類級(jí)別攔截器

    quarkus依賴注入之十二:禁用類級(jí)別攔截器

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》系列的第十二篇,繼續(xù)學(xué)習(xí)攔截器的另一個(gè)高級(jí)特性:禁用類級(jí)別攔截器 本篇由以下內(nèi)容構(gòu)成 編碼驗(yàn)證類攔截器和方法攔截器的疊加效果 用注解 NoClassInterceptors 使類攔截器

    2024年02月13日
    瀏覽(53)
  • quarkus依賴注入之十三:其他重要知識(shí)點(diǎn)大串講(終篇)

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

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》系列的終篇,前面十二篇已覆蓋quarkus依賴注入的大部分核心內(nèi)容,但依然漏掉了一些知識(shí)點(diǎn),今天就將剩下的內(nèi)容匯總,來個(gè)一鍋端,輕松愉快的結(jié)束這個(gè)系列 總的來說,

    2024年02月13日
    瀏覽(26)
  • quarkus依賴注入之十一:攔截器高級(jí)特性上篇(屬性設(shè)置和重復(fù)使用)

    quarkus依賴注入之十一:攔截器高級(jí)特性上篇(屬性設(shè)置和重復(fù)使用)

    這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos 本篇是《quarkus依賴注入》系列的第十一篇,之前的[《攔截器》]學(xué)習(xí)了攔截器的基礎(chǔ)知識(shí),現(xiàn)在咱們要更加深入的了解攔截器,掌握兩種高級(jí)用法:攔截器屬性和重復(fù)使用攔截器 先來回顧攔截器的基

    2024年02月13日
    瀏覽(49)
  • Springboot依賴注入Bean的三種方式,final+構(gòu)造器注入Bean

    @Autowired注解的一大使用場(chǎng)景就是Field Injection。 通過Java的反射機(jī)制實(shí)現(xiàn),所以private的成員也可以被注入具體的對(duì)象 優(yōu)點(diǎn) 代碼少,簡(jiǎn)潔明了。 新增依賴十分方便,不需要修改原有代碼 缺點(diǎn) 容易出現(xiàn)空指針異常。Field 注入允許構(gòu)建對(duì)象實(shí)例時(shí)依賴的對(duì)象為空,導(dǎo)致空指針異常

    2024年02月02日
    瀏覽(22)
  • 基于Xml方式Bean的配置-Bean的依賴注入以及·自動(dòng)裝配

    基于Xml方式Bean的配置-Bean的依賴注入以及·自動(dòng)裝配

    Bean的依賴注入方式 注入方式 配置方式 通過Bean的set方法注入 通過構(gòu)造Bean的方法進(jìn)行注入 其中,ref是reference的縮寫形式,翻譯為:涉及,參考的意思,用于引用其它Bean的id,value用于指定屬性值 注入數(shù)據(jù)類型 普通數(shù)據(jù)類型:String、int、boolean,通過value屬性指定 引用數(shù)據(jù)類型

    2024年02月07日
    瀏覽(27)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包