??????? 在你學(xué)到了如何開發(fā)藕合松散的服務(wù)組件后,為了存取那些服務(wù)對(duì)象,你需要通過服務(wù)器的JNDI 來查找存根對(duì)象(session bean)或消息隊(duì)列(MDB)。JNDI查找是把客戶端與實(shí)際的服務(wù)端實(shí)現(xiàn)解藕的關(guān)鍵步驟。但是,直接使用一個(gè)字符串來進(jìn)行JNDI查找并不優(yōu)雅。有這樣幾個(gè)原因:
·客戶端與服務(wù)端必須有一致的基于字符串的名字。它沒有在編譯時(shí)得到認(rèn)證或在布署時(shí)得到檢查。
·從JNDI返回的服務(wù)對(duì)象的類型沒有在編譯時(shí)進(jìn)行檢查,有可能在運(yùn)行時(shí)出現(xiàn)轉(zhuǎn)換(casting)錯(cuò)誤。
·冗長的查找代碼,有著自己的try-catch代碼塊,在應(yīng)用之間是重復(fù)的和雜亂的
?????????EJB 3.0,對(duì)任何POJO,提供了一個(gè)簡單的和優(yōu)雅的方法來解藕服務(wù)對(duì)象和資源。使用@EJB注釋,你可以將EJB存根對(duì)象注入到任何EJB 3.0容器管理的POJO 中。如果注釋用在一個(gè)屬性變量上,容器將會(huì)在它被第一次訪問之前賦值給它。在Jboss下一版本中@EJB注釋從javax.annotation包移到了javax.ejb 。
下面的例子演示了怎樣把HelloWorldBean無狀態(tài)session bean的存根注入到InjectionBean類中。
InjectionBean.java
//author:lihuoming
package com.foshanshop.ejb3.impl;
import com.foshanshop.ejb3.HelloWorld;
import com.foshanshop.ejb3.Injection;
import javax.annotation.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote ({Injection.class})
public class InjectionBean implements Injection {
@EJB (beanName="HelloWorldBean")
HelloWorld helloworld;
public String SayHello() {
return helloworld.SayHello("注入者");
}
}
@EJB注釋的beanName屬性指定EJB的類名(不帶包名),他的另一個(gè)屬性mappedName指定Bean實(shí)例的JNDI名。
下面的片斷演示了如何使用beanName 或mappedName屬性查找HelloWorldBean 會(huì)話bean
public class InjectionBean implements Injection {
@EJB (beanName="HelloWorldBean")
//@EJB (mappedName="HelloWorldBean/remote")
HelloWorld helloworld;
…..
@EJB注釋如果被用在JavaBean風(fēng)格的setter 方法上時(shí),容器會(huì)在屬性第一次使用之前,自動(dòng)地用正確的參數(shù)調(diào)
用bean的setter 方法。下面的片斷演示了這是如何做的
public class InjectionBean implements Injection {
HelloWorld helloworld;
@EJB (beanName="HelloWorldBean")
public void setHelloworld(HelloWorld helloworld) {
this.helloworld = helloworld;
}
…..
下面是InjectionBean的Remote業(yè)務(wù)接口
Injection.java
//author:lihuoming
package com.foshanshop.ejb3;
public interface Injection {
public String SayHello();
}
下面是Session Bean的JSP 客戶端代碼:
InjectionTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.Injection, javax.naming.*, java.util.Properties"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx;
try {
ctx = new InitialContext(props);
Injection injection = (Injection) ctx.lookup("InjectionBean/remote");
out.println(injection.SayHello());
} catch (NamingException e) {
out.println(e.getMessage());
}
%>
@EJB注釋只能注入EJB存根對(duì)象,除@EJB注釋之外,EJB 3.0也支持@Resource注釋來注入來自JNDI的任何
資源。下面的例子中演示了如何注入數(shù)據(jù)源。"java:/DefaultMySqlDS"是數(shù)據(jù)源DefaultMySqlDS的全局JNDI名。
有關(guān)數(shù)據(jù)源的配置請(qǐng)參考后面章節(jié)“JBoss數(shù)據(jù)源的配置”
//author:lihuoming
package com.foshanshop.ejb3.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.foshanshop.ejb3.HelloWorld;
import com.foshanshop.ejb3.Injection;
import javax.annotation.EJB;
import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.sql.DataSource;
@Stateless
@Remote ({Injection.class})
public class InjectionBean implements Injection {
@EJB (beanName="HelloWorldBean")
HelloWorld helloworld;
@Resource (mappedName="java:/DefaultMySqlDS")
DataSource myDb;
public String SayHello() {
String str = "";
try {
Connection conn = myDb.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT studentName FROM student");
if (rs.next()) {
str = rs.getString(1);
}
rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
return helloworld.SayHello(str);
}
}
????????????如果JNDI對(duì)象在本地(java:comp/env)JNDI目錄中,你只需給定他的映謝名稱即可,不需要帶前綴,如下面例子注入一個(gè)消息connection factory和一個(gè)messaging queue
@Resource (mappedName="ConnectionFactory")
QueueConnectionFactory factory;
@Resource (mappedName="queue/A")
Queue queue;
對(duì)于"well-known"對(duì)象,@Resource注釋可以不指定JNDI名就能注入他們,他通過變量的類型就能獲得他的JNDI名。下面是一些例子。
@Resource
TimerService tms;
@Resource
SessionContext ctx;
和@EJB注釋相同, @Resource注釋也可以被用在JavaBean風(fēng)格的setter 方法上。
本例子的EJB源代碼在DependencyInjection文件夾(源代碼:http://www.foshanshop.net/),項(xiàng)目中使用到的類庫在上級(jí)目錄lib 文件夾下。要恢復(fù)DependencyInjection項(xiàng)目的開發(fā)環(huán)境請(qǐng)參考第三章”如何恢復(fù)本書配套例子的開發(fā)環(huán)境”,要發(fā)布本例子EJB,你可以執(zhí)行Ant 的deploy任務(wù)。發(fā)布前確保HelloWorld.jar 已經(jīng)發(fā)布到Jboss中。
posted on 2006-11-01 00:37
凌宇 閱讀(1184)
評(píng)論(0) 編輯 收藏