JavaEE中的依賴性——依賴尋找,javaee依賴性依賴
關於依賴性管理我們要介紹的第一個策略就是依賴尋找(dependency lookup)。這種策略是JavaEE中傳統形式的依賴性管理,這裡可以看到JavaEE規範中的JNDI(Java Naming andDirectoryInterface)的身影。從名字就可以看出來這裡解決依賴性是通過尋找的方式。
就像上篇文章提到的,所要引用的資源是通過一對name與target對應的註解標識的。name用來表明此資源被依賴時候的名字,所以當資源註解放在類定義之上的時候需要為其起個名字。但是如果資源註解放在一個欄位或者一個setter方法之上那麼將不需要為其起名字。一般情況下當使用依賴尋找時,註解是放在類上的,並且顯式的指定名稱。將註解放置在一個欄位或者setter方法上的使用方式下一篇部落格再討論。
指定name的作用是為調用者動態解析引用提供便利。因為JNDI是JavaEE的規範所以所有的JavaEE應用伺服器都會支援JNDI,而且對於每個組件來說都有其自己局部範圍的JNDI命名內容,稱為環境命名內容。當通過JNDI尋找某個資源的時候就是在其環境命名內容中根據預先定義好的名稱進行尋找。下面代碼就掩飾了如何運用依賴尋找為一個EJB組件進行服務的。
@Stateless@EJB(name="audit", beanInterface=AuditService.class)public class DepartmentServiceBean implements DepartmentService { private AuditService audit; @PostConstruct public void init() { try { Context ctx = new InitialContext(); audit = (AuditService) ctx.lookup("java:comp/env/audit"); } catch (NamingException e) { throw new EJBException(e); } } public void performAudit() { audit.audit(); } // ...}
可以看到DeptServiceBean是一個會話bean。它使用@EJB註解聲明了一個會話bean的依賴性,並把其命名為“audit”。@EJB註解的beanInterface元素引用了這個會話bean中需要的業務介面(AuditService)。在init方法中尋找並得到了相應的資源,其中Context和IitialContext介面都是JNDI所定義的。Context介面的lookup()方法是用於從JNDI上下文檢索對象的主要方法。為了找到命名為“audit”的引用,應用程式將尋找名稱“java:comp/env/audit”,並把結果轉換到AuditService業務介面。添加到引用名稱的首碼“java:comp/env”指示伺服器應該使用環境命名上下問來搜尋和發現引用。如果制定了錯誤的名稱,那麼當查詢失敗時將會拋出一個異常。
JNDI這種方式解決依賴性問題是通用的,只要符合JavaEE標準那麼就可以使用這種尋找的方式找到自己關心的介面(其實最終幹活的是實現)但是這種尋找資源的方法有些繁瑣,類似於家裡著火了再去買消防器材(為什麼不提前買好呢?這是我們下一篇部落格要說的)。
除了上面代碼中使用Context介面的lookup方法,EJB還可以使用EJBContext介面(以及它的子介面)的lookup方法。這樣就可以在程式運行時訪問其中的服務(計時服務?)下面的代碼就示範了這種方式的lookup方法。
@Stateless@EJB(name="audit310", beanInterface=AuditService310.class)public class DepartmentServiceBean310 implements DepartmentService310 { // use of resource dependency injection is covered later in the chapter @Resource SessionContext context; AuditService310 audit; public void setSessionContext(SessionContext context) { this.context = context; } @PostConstruct public void init() { audit = (AuditService310) context.lookup("audit310"); } public void performAudit() { audit.audit(); } // ...}
儘管網上很多人說相比JNDIAPI,EJBContext lookup()方法有優勢。首先方法的參數恰好是在資源引用中指定的名稱,不用再寫第一部分代碼中奇怪的字串了。其次是關於異常的處理,顯而易見第二種方式中異常已經不用我們手動處理了,因為第二種方法直接拋出運行時異常。其實在容器內部還是會像第一種方法那樣去調用JNDI API去尋找,但是容易已經為我們處理了異常,這就導致第二種方式看上去好像不用處理以上了似的。在筆者看來這兩種方式都不是最適合我們的方式,就如同上面的舉得例子,著火了才想著去買消防器材,為什麼不提前買好呢?這就是我們下一篇部落格要介紹的另一種解決依賴性的策略——依賴性注入。