
原始链接
作为轻量级容器,通常认为Spring是EJB的替代方案. 我们认为,对于大多数(如果不是大多数)领域的应用程序和用例,Spring作为容器结合了其对事物,ORM和JDBC访问的丰富支持,这不仅仅是通过EJB容器和EJB实现相同的功能. 不错的选择.
然后,请注意,使用Spring不会阻止您使用EJB. 实际上,Spring使访问EJB以及实现EJB及其功能变得更加容易. 此外,使用Spring获取EJB提供的服务可以使这些服务在本地EJB,远程EJB或POJO(普通Java对象)变量之间透明切换,而无需更改客户端代码.
在本章中,我们将看到Spring如何使您能够获取和实现EJB. 当访问无状态会话组件(SLSB)时,Spring提供了特定的值,因此我们从这里开始讨论.
在本地或远程无状态会话组件中调用方法. 客户端代码通常必须执行JNDI查找以获取本地或远程EJB Home对象,然后使用“创建”方法获取实际(本地或远程)EJB对象. 然后,将在EJB中调用一个或多个方法.

为了避免底层代码的重复,许多EJB应用程序使用服务定位器和业务代表模式. 它们比在客户端代码中各处都使用JNDI查找要好,但是也存在明显的缺点,例如:
假设我们有一个需要使用本地EJB的Web容器. 我们将遵循最佳实践,并使用EJB业务方法接口模式,因此EJB的本地接口扩展了不是特定于EJB的业务方法接口. 我们将此接口称为MyComponent.
public interface MyComponent {
...
}
使用业务方法接口模式的主要原因是确保本地接口中的方法签名和Bean实现类同步是自动的. 另一个原因是,它使我们可以在需要时更轻松地转换为POJO来实现此服务. 当然,我们还需要实现本地home接口,并提供一个实现类来实现SeesionBean和MyComponent业务方法接口. 现在,我们唯一需要的Java代码是在控制器中公开setter方法,以设置MyComponent将Web层控制器连接到此EJB实现. 这会将引用另存为实例变量在容器中:
private MyComponent myComponent;
public void setMyComponent(MyComponent myComponent) {
this.myComponent = myComponent;
}

然后我们可以在此控制器的任何业务方法中使用此实例变量. 现在假设我们在Spring控制器之外获取控制器对象,我们可以(在相同上下文中)配置LocalStatelessSessionProxyFactoryBean实例,该实例是EJB代理对象. 代理程序的配置和控制器的myComponet属性的值在一个配置项中完成,如下所示:
<bean id="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myBean"/>
<property name="businessInterface" value="com.mycom.MyComponent"/>
</bean>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
尽管您没有义务使用AOP概念来享受此结果,但Spring AOP框架在有效执行此配置方面做了很多工作. myComponetbean定义了实现业务接口的EJB代理. 此EJB本地主目录将在启动时进行缓存,因此只有一个JNDI查找. 每当调用此EJB时,代理都会调用本地EJB的classname方法,并在EJB上调用相应的业务方法.
myControllerbean定义为此EJB代理设置控件类的myComponet属性.
可选(最好在许多此类代理定义的情况下),请考虑使用

<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"
business-interface="com.mycom.MyComponent"/>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>
这种EJB获取机制极大地简化了应用程序代码: Web层代码(或其他EJB客户端代码)不依赖于EJB的使用. 如果要使用POJO或模拟对象而不是此EJB引用来获取其他测试堆,则可以简单地修改此myComponetbean的定义,而无需修改任何Java代码. 此外,我们无需在应用程序中编写任何JNDI查找行或其他EJB样板代码.
基准和其他实际应用表明,此方法的性能开销(涉及目标EJB的反射调用)非常小,通常在使用中无法检测到. 请记住,由于在应用程序服务器中使用EJB基础结构的开销,我们不希望以细粒度的方式导出EJB.
有关于JNDI查找的警告. 在bean容器中,最好将类用作单例(将其用作原型似乎是不合理的). 但是,如果Bean容器预先实例化了单例,则如果Bean容器位于EJB中,则可能会遇到问题. 在加载容器之前先加载了目标EJB. 因为此JNDI查找将在此类的init()方法中调用并进行缓存,但是此EJB尚未绑定到相应的目标地址. 解决此问题的方法不是提前实例化工程对象,而是在首次使用它时创建它. 在XML容器中,它由lazy-init属性控制.
尽管这并不是大多数Spring用户的兴趣,但是那些使用EJB进行AOP编程的人可能想看看LocalSlsbInvokerInterceptor

获取远程EJB与获取本地EJB基本相同,除了将使用SimpleRemoteStatelessSessionProxyFactoryBean或
Spring的EJB客户端再次比非Spring方法更具优势. EJB客户端代码在本地和远程调用EJB之间轻松切换通常是有问题的. 因为远程接口方法必须声明它们可能会引发RemoteException,并且客户端代码必须对其进行处理,所以本地接口没有此异常. 如果将用于处理本地EJB的客户端代码更改为处理远程EJB,通常需要对其进行修改以增加对远程异常的处理,并且如果客户端最初需要处理远程EJB,则用于处理本地EJB的代码可以保持不变. ,但是要处理远程异常很多不必要的操作,否则您需要删除这部分代码. 您可以使用Spring的远程EJB代理,而无需声明任何引发RemoteException并实现EJB代码的业务方法接口. 有一个远程接口,除了抛出异常外,其他接口完全相同,但是依赖于代理来动态处理这两个接口以使它们的行为相同. 这样,无需处理客户代码
RemoteException类. 在此EJB调用期间抛出的所有RemoteException都将作为RemoteAccessException类再次抛出,而无需取消选中. 此类是RuntimeException的子类. 无需客户端代码知识ejb,即可在本地EJB或远程EJB(甚至简单的Java对象)实现之间切换此目标服务. 当然,这是可选的. 您还可以在您的业务界面中声明RemoteException.
通过Spring获得EJB 2.x会话组件和EJB3会话组件基本上是透明的. Spring的EJB提取程序包含
注意: 对于EJB 3会话组件,您也可以直接使用JndiObjectFactoryBean / jee: jndi-lookup,因为此处将完全有效的组件引用公开给JNDI loolup. 定义显示的
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-209146-1.html
猪狗不如