荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: junire (好好学习,天天向上), 信区: Java
标 题: java应用的动态扩展(二)
发信站: 荔园晨风BBS站 (Sat Nov 17 21:53:02 2001), 转信
EJB应用的扩展
在普通Java应用中使用的技术往往不适用于EJB。EJB 2.0规范建议我们只通过
Home接口创建EJB对象。之所以要强调这一点,是因为容器需要对EJB对象的创建和
拆除有更多的控制权,以便实现更好的缓冲池管理和提高代码可重用性。在EJB环
境中,所有的业务方法都在远程对象上调用,然后这些调用被传递到相应的EJB对
象上执行。因此,客户程序只需要可以在它上面调用业务方法的远程对象。下面我
们来看看如何根据指定的类名字获得EJB的远程对象。
所有EJB远程接口都必须遵循EJB规范。例如,所有的远程接口必须从一个Sun提供
的公共接口javax.ejb.EJBObject派生。由于我们要求不同的产品在动态调用时有
类似的行为模式,所以各种产品都必须从一个公共的接口Product继承,而
Product又从javax.ejb.EJBObject继承。Listing 6显示了该接口的代码。
【Listing 6:公共的Product接口】
// Product.java
package com.test.dynamic;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface Product extends EJBObject
{
public float calculatePremium(
float faceValue , int term , int age) throws
RemoteException;
}
按照EJB规范,每一个Bean应该有自己的远程接口。因此,本文例子中的各种产品
都必须有自己的远程接口。容器会自动为这些远程接口提供实现。在部署Bean的时
候,容器将确保每一个Bean都有各自的远程接口。注意MediCare接口扩展自
Product接口,它不应该再定义calculatePremium()方法,因为父接口已经定义了
这个方法(见Listing 7)。图二显示了MediCare和LifeCare接口以及它们各自的
Bean实现,MediCareBean和LifeCareBean。在这里,MediCare和LifeCare接口没有
定义任何附加的方法
【Listing 7:从Product接口派生的两个接口和MediCareBean】
// MediCare.java
package com.test.dynamic;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface MediCare extends Product
{
// 不再定义calculatePremium方法
}
// LifeCare.java
package com.test.dynamic;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface LifeCare extends Product
{
// 不再定义calculatePremium方法
}
// MediCareBean.java
package com.test.dynamic;
import javax.ejb.*;
import java.util.*;
import javax.naming.*;
/**
* @stereotype SessionBean
* @remoteInterface com.test.dynamic.MediCareBean
* @homeInterface com.test.dynamic.MediCareHome
* @statemode Stateless
*/
public class MediCareBean implements javax.ejb.SessionBean
{
// 构造函数
public MediCareBean()
{ }
// ----------------------------------------------------
// SessionBean接口实现
public void ejbActivate(){}
public void ejbPassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ctx)
{ this.ctx = ctx;
}
// -----------------------------------------------------
// create方法
public void ejbCreate(){}
// -----------------------------------------------------
// 业务方法
public float calculatePremium(
float faceValue , int term , int age)
{
float premium ;
// 执行计算
// Premium == ??
return premium;
}
// -----------------------------------------------------
private SessionContext ctx;
}
LifeCareBean的实现也相似,只是保险费计算方法的逻辑不同。Home接口都相似。
我们来看一下MediCareHome接口:
// MediCareHome.java
package com.test.dynamic;
import javax.ejb.*;
import java.rmi.RemoteException;
public interface MediCareHome extends EJBHome
{
public MediCare create() throws CreateException, RemoteException;
}
由于create()方法面向特定的Home对象,要创建某个远程接口,我们必须获得特定
的Home对象。能够创建MediCare远程对象的唯一对象是MediCareHome对象。下面是
通常使用的Home对象查找代码:
try
{
// 假定已经设置好合适的环境
Context ctx = new InitialContext(new Properties());
MediCarehome objHome = (MediCarehome) ctx.lookup("MediCarehome");
// 获得远程对象
MediCare objMediCare = objHome.create();
// 调用各种业务方法
}
catch (Exception e)
{ e.printStackTrace(); }
因此,为创建MediCare远程对象,我们需要一个MediCareHome对象(由容器实现)
。对于LifeCare远程对象来说,情况也一样。这里的关键在于要编写出通用的代码
,在Home对象上调用create()方法获取各自的远程对象。Home对象通过查找JNDI环
境获得。由于在本例中,create()方法返回一个Product类型的接口,我们可以调
用该接口的calculatePremium()方法,这个调用随后又将被分派到后台EJB的
calculatePremium()方法。
现在,为调用可能出现的未知对象上的方法,我们要用到Java Reflection API。
我们感兴趣的是java.lang.reflect包的Method类,该类代表的是一个Java方法。
java.lang.reflect.Method的invoke方法用来调用Method对象所代表的特定方法。
invoke方法的语法是:
public Object invoke(Object obj, Object [] args)
Home接口和产品的名称可以从XML文件得到(对于EJB,保存Bean的Home名称而不是
类的全称),随后这些信息就被用于通过JNDI查找Home对象。下面是XML文件的一
个片断:
【Listing 8:EJB环境下的XML文件】
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<Product>
<Product-name>MediCare</Product-name>
<Home-name>MediCareHome</Home-name>
</Product>
<Product>
<Product-name>LifeCare</Product-name>
<Home-name>LifeCareHome</Home-name>
</Product>
<Product>
<Product-name>XYZCare</Product-name>
<Home-name>XYZCareHome</Home-name>
</Product>
</root>
从Home名称得到远程对象的代码封装在getProductFromHome()方法里面。它查找
Home对象,利用类的getMethod()获得一个指向create()方法的句柄。然后,它调
用不带参数的create()方法,利用Method.invoke()返回一个Product类型的接口。
参见Listing 9。
【Listing 9:根据Home名称返回远程对象】
public Product getProductFromHome(
String strHome)throws Exception
{
// 待返回的Product接口
Product prodRemote= null;
// create方法
java.lang.reflect.Method create;
// 参数类型
Class[] parameterTypes = new Class[] {};
// 参数
Object[] arguments = new Object[] {};
try
{
// 环境信息
Context ctx = new InitialContext( new Properties());
// 查找Home对象
EJBHome iHome = (EJBHome)ctx.lookup(strHome);
Class cls = iHome.getClass();
// 寻找参数类型为parameterTypes的方法
create = cls.getMethod("create", parameterTypes);
// 调用该方法获得远程接口
prodRemote = (Product)create.invoke(iHome, arguments);
}
catch( Exception e )
{
// 处理异常
throw e;
}
// 返回远程接口
return prodRemote;
}
由于我们获得的是Product类型的接口,所以可以调用该接口的
calculatePremium()方法。根据多态性原理,该调用将传递到隐藏在远程对象之后
的对象所实现的方法:
Try
{
// 获得特定产品类型的远程对象
Product objProd = getProductFromHome("MediCare");
// 调用该产品类型的calculatePremium方法
Float premium = objProd.calculatePremium(face-value, term, age);
// 显示保险费
// ......
}
catch (Exception e)
{ e.printStackTrace(); }
正如本例所示,只要更新XML文件和部署合适的EJB,我们可以添加任何额外的产品
。应用程序可以在运行时找到新的Bean并调用其calculatePremium()方法,从而提
供真正的动态扩展支持。
--
曾经有个Cstrike的game让我痴迷,为了这份这份痴迷,我要把它记在
心里,如果Cstrike是灌冰红茶的话,我希望它永远有人喜欢,如果非要加个期限的话,
我希望是一万年。但是,我现在不得不暂时告别它了,虽然很痛苦,但我很坚定。。。。
。。。我还有更重要的事要做。。。。
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.180]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店