ejb生命周期_EJB 3.x:生命周期和并发模型(第1部分)
ejb生命周期
對于經驗豐富的專業人員來說,Java EE組件生命周期和與并發相關的詳細信息可能不是新知識,但是對于初學者來說,這可能會花費一些時間。
就EJB而言,了解其生命周期 (以及相關的并發場景)對于確保使用EJB的正確用法和解決方案設計至關重要。 容易濫用它們!
豆的生命周期
我將在這篇文章中快速介紹無狀態和有狀態的 bean,暫時跳過Lima Beans!
- 有狀態會話Bean –生命周期+并發處理
- 無狀態 bean –僅用于并發模型,因為我在之前的一篇文章中曾簡要介紹了生命周期。
有狀態會話Bean的生命周期中有哪些不同的狀態?
- 不存在
- 準備
- 鈍化的
是什么觸發了他們?
這是一個快速的表格快照和一個高級圖表。 有關更多詳細信息,請繼續閱讀。 。 。
無狀態會話Bean生命周期狀態圖
注意 :DNE –不存在, R –就緒, P –鈍化,SFSB –有狀態會話Bean
| DNE轉R | 首次通過JNDI或DI訪問SFSB實例時 | @PostConstruct |
| R到DNE | 容器關閉,客戶端調用用@Remove注釋的方法,Bean達到由DD或@StatefulTimeout指定的空閑超時閾值 | @PreDestroy |
| R到P | EJB容器會鈍化閑置的bean,并根據特定算法將其從活動內存中刪除 | @PrePassivate |
| P到DNE | Bean達到由DD或@StatefulTimeout指定的空閑超時閾值 | 注意 :@PreDestroy注釋的方法不會被調用 |
| 從P到R | 客戶端被鈍化但尚未超時后調用SFSB實例時 | @PostActivate |
注意 :如果SFSB在請求處理期間引發異常,則其實例將被破壞,即進入DNE狀態。 在這種情況下,不會調用@PreDestroy注釋方法
現在我們對SFSB的生命周期有了一些了解,讓我們嘗試看一下這些Bean在負載下的行為,即當多個用戶一次使用該應用程序時,它轉化為并發訪問SFSB實例。
有狀態會話Bean:并發管理
線程安全是EJB的核心功能之一。 要注意的一點是,此線程安全性是免費的,并且不需要任何與并發相關的構造都可以由Bean開發人員自己進行編碼 (有一些例外 )。 就SFSB而言,EJB容器確保在特定時間只有一個線程可以訪問bean實例。
在此示例中,我們嘗試通過JMeter調用測試Servlet來模擬對SFSB單個實例的并發訪問 。 Servlet通過DI注入bean并在其上調用方法。 SFSB方法僅使用Thread.sleep()假裝好像正在執行某些操作。
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進行并發請求模擬
觀察結果
- 由于Servlet本身不是線程安全的,因此實際上有多個線程將進入doGet()方法
- 并發訪問SFSB的單個實例(通過hashCode結果證明)(請參見記錄的語句中的線程名稱)
- 但是,只有一個線程將能夠訪問SFSB實例-其他線程在SFSB方法返回時等待其輪換。 通過控制臺上的日志語句可以明顯看到此延遲
控制臺日志
無狀態豆呢?
這些bean 本質上是線程安全的 。 為什么呢 這是因為默認情況下,容器確保每個新請求都由 Bean 的新實例提供服務。 請記住,客戶端可以通過3種可能的方式獲得對無狀態bean的引用-DI,JNDI或通過遠程接口(RMI)。 在所有這些情況下,都是容器(代理)攔截了該調用–因此,即使看似多個線程正在訪問同一bean實例,它實際上也不是同一實例!
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();}}觀察結果
- 由于Servlet本身不是線程安全的,因此實際上有多個線程將進入doGet()方法
- 容器正在選擇SLSB的不同實例 (通過hashCode結果顯而易見)來管理并發請求(請參見記錄的語句中的線程名稱)。
- 盡管有并發請求,但每個請求線程都由一個新實例提供服務
控制臺日志
目前為止就這樣了! 我計劃在以后的文章中介紹Singleton Session bean。 敬請關注 。 。 。 。
謝謝閱讀!
翻譯自: https://www.javacodegeeks.com/2014/08/ejb-3-x-lifecycle-and-concurrency-models-part-1.html
ejb生命周期
總結
以上是生活随笔為你收集整理的ejb生命周期_EJB 3.x:生命周期和并发模型(第1部分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 缴纳备案金是什么意思(缴纳备案金)
- 下一篇: Quarkus on OpenJ9 JV