ejb生命周期_EJB 3.x:生命周期和并发模型(第1部分)
ejb生命周期
對于經(jīng)驗(yàn)豐富的專業(yè)人員來說,Java EE組件生命周期和與并發(fā)相關(guān)的詳細(xì)信息可能不是新知識,但是對于初學(xué)者來說,這可能會(huì)花費(fèi)一些時(shí)間。
就EJB而言,了解其生命周期 (以及相關(guān)的并發(fā)場景)對于確保使用EJB的正確用法和解決方案設(shè)計(jì)至關(guān)重要。 容易濫用它們!
豆的生命周期
我將在這篇文章中快速介紹無狀態(tài)和有狀態(tài)的 bean,暫時(shí)跳過Lima Beans!
- 有狀態(tài)會(huì)話Bean –生命周期+并發(fā)處理
- 無狀態(tài) bean –僅用于并發(fā)模型,因?yàn)槲以谥暗囊黄恼轮性喴榻B了生命周期。
有狀態(tài)會(huì)話Bean的生命周期中有哪些不同的狀態(tài)?
- 不存在
- 準(zhǔn)備
- 鈍化的
是什么觸發(fā)了他們?
這是一個(gè)快速的表格快照和一個(gè)高級圖表。 有關(guān)更多詳細(xì)信息,請繼續(xù)閱讀。 。 。
無狀態(tài)會(huì)話Bean生命周期狀態(tài)圖
注意 :DNE –不存在, R –就緒, P –鈍化,SFSB –有狀態(tài)會(huì)話Bean
| DNE轉(zhuǎn)R | 首次通過JNDI或DI訪問SFSB實(shí)例時(shí) | @PostConstruct |
| R到DNE | 容器關(guān)閉,客戶端調(diào)用用@Remove注釋的方法,Bean達(dá)到由DD或@StatefulTimeout指定的空閑超時(shí)閾值 | @PreDestroy |
| R到P | EJB容器會(huì)鈍化閑置的bean,并根據(jù)特定算法將其從活動(dòng)內(nèi)存中刪除 | @PrePassivate |
| P到DNE | Bean達(dá)到由DD或@StatefulTimeout指定的空閑超時(shí)閾值 | 注意 :@PreDestroy注釋的方法不會(huì)被調(diào)用 |
| 從P到R | 客戶端被鈍化但尚未超時(shí)后調(diào)用SFSB實(shí)例時(shí) | @PostActivate |
注意 :如果SFSB在請求處理期間引發(fā)異常,則其實(shí)例將被破壞,即進(jìn)入DNE狀態(tài)。 在這種情況下,不會(huì)調(diào)用@PreDestroy注釋方法
現(xiàn)在我們對SFSB的生命周期有了一些了解,讓我們嘗試看一下這些Bean在負(fù)載下的行為,即當(dāng)多個(gè)用戶一次使用該應(yīng)用程序時(shí),它轉(zhuǎn)化為并發(fā)訪問SFSB實(shí)例。
有狀態(tài)會(huì)話Bean:并發(fā)管理
線程安全是EJB的核心功能之一。 要注意的一點(diǎn)是,此線程安全性是免費(fèi)的,并且不需要任何與并發(fā)相關(guān)的構(gòu)造都可以由Bean開發(fā)人員自己進(jìn)行編碼 (有一些例外 )。 就SFSB而言,EJB容器確保在特定時(shí)間只有一個(gè)線程可以訪問bean實(shí)例。
在此示例中,我們嘗試通過JMeter調(diào)用測試Servlet來模擬對SFSB單個(gè)實(shí)例的并發(fā)訪問 。 Servlet通過DI注入bean并在其上調(diào)用方法。 SFSB方法僅使用Thread.sleep()假裝好像正在執(zhí)行某些操作。
package com.abhirockzz.wordpress.ejb.lifecycle.stateful;import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateful;@Stateful public class MyStatefulBean {public MyStatefulBean() {}public void act() {System.out.println("Entered MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException ex) {Logger.getLogger(MyStatefulBean.class.getName()).log(Level.SEVERE, null, ex);}System.out.println("Exit MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());} }package com.abhirockzz.wordpress.ejb.lifecycle.stateful;import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;@WebServlet(name = "SFSBTestServlet", urlPatterns = {"/SFSBTestServlet"}) public class SFSBTestServlet extends HttpServlet {public SFSBTestServlet() {}@InjectMyStatefulBean mySFSB;@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("Entered SFSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());mySFSB.act();}}通過JMeter的HTTP GET請求
通過JMeter進(jìn)行并發(fā)請求模擬
觀察結(jié)果
- 由于Servlet本身不是線程安全的,因此實(shí)際上有多個(gè)線程將進(jìn)入doGet()方法
- 并發(fā)訪問SFSB的單個(gè)實(shí)例(通過hashCode結(jié)果證明)(請參見記錄的語句中的線程名稱)
- 但是,只有一個(gè)線程將能夠訪問SFSB實(shí)例-其他線程在SFSB方法返回時(shí)等待其輪換。 通過控制臺上的日志語句可以明顯看到此延遲
控制臺日志
無狀態(tài)豆呢?
這些bean 本質(zhì)上是線程安全的 。 為什么呢 這是因?yàn)槟J(rèn)情況下,容器確保每個(gè)新請求都由 Bean 的新實(shí)例提供服務(wù)。 請記住,客戶端可以通過3種可能的方式獲得對無狀態(tài)bean的引用-DI,JNDI或通過遠(yuǎn)程接口(RMI)。 在所有這些情況下,都是容器(代理)攔截了該調(diào)用–因此,即使看似多個(gè)線程正在訪問同一bean實(shí)例,它實(shí)際上也不是同一實(shí)例!
package com.abhirockzz.wordpress.ejb.lifecycle.stateless;import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateless;@Stateless public class MyStatelesslBean {public void act() {System.out.println("Entered MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException ex) {Logger.getLogger(MyStatelesslBean.class.getName()).log(Level.SEVERE, null, ex);}System.out.println("Exit MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());} }package com.abhirockzz.wordpress.ejb.lifecycle.stateless;import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;@WebServlet(name = "SLSBTestServlet", urlPatterns = {"/SLSBTestServlet"}) public class SLSBTestServlet extends HttpServlet {@InjectMyStatelesslBean slsb;@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("Entered SLSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName());slsb.act();}}觀察結(jié)果
- 由于Servlet本身不是線程安全的,因此實(shí)際上有多個(gè)線程將進(jìn)入doGet()方法
- 容器正在選擇SLSB的不同實(shí)例 (通過hashCode結(jié)果顯而易見)來管理并發(fā)請求(請參見記錄的語句中的線程名稱)。
- 盡管有并發(fā)請求,但每個(gè)請求線程都由一個(gè)新實(shí)例提供服務(wù)
控制臺日志
目前為止就這樣了! 我計(jì)劃在以后的文章中介紹Singleton Session bean。 敬請關(guān)注 。 。 。 。
謝謝閱讀!
翻譯自: https://www.javacodegeeks.com/2014/08/ejb-3-x-lifecycle-and-concurrency-models-part-1.html
ejb生命周期
總結(jié)
以上是生活随笔為你收集整理的ejb生命周期_EJB 3.x:生命周期和并发模型(第1部分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 缴纳备案金是什么意思(缴纳备案金)
- 下一篇: Quarkus on OpenJ9 JV