- EJB是sun的JavaEE服务器端组件模型,是一种规范,设计目标与核心应用是部署分布式应用程序。
- EJB2.0过于复杂,EJB3.0的推出减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。
- EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力承诺的组件。
相比EJB3以前的版本而言,增加了两个新特性:元数据注解(Annotation) 和依赖注入(Injection),而元数据注解以最大限度的使部署描述符从冗余繁杂中脱离出来。
EnterpriseBean和Serializable接口一样,是一个标记性接口。用于标记一个类为一个Bean。它有三种实现:SessionBean,EntityBean,MessageDrivenBean。
SessionBean:它是对业务逻辑的封装,类似于我们经常写的Service层。它可以以local, remote, webservice 服务的方式被client调用。
EntityBean:它是对数据库对象的封装,一个EntityBean,就是数据库的一条记录。
MessageDrivenBean:一个messageDrivenBean其实就是一个javax.jms.MessageListener。在JMS中有MessageConsumer,它支持两种接收消息的方式:同步接收采用MessageConsumer#receive()方法,异步接收则是为MessageConsumer设置一个MessageListener,一旦接收到消息,就调用listener#onMessage()。
1、SessionBean服务组件
SessionBean服务端有三大组件Home、EJbObject、SessionBean。
SessionBean是我们编写业务逻辑的地方。譬如数据库操作,进行计算等等。但是它对于客户端是不可见的,一个SessionBean实例的创建、销毁、激活、钝化等都是由EJB容器来管理的。
EJBObject:你可以将EJBObject看作是SessionBean对象的Proxy。需要将你的业务方法同样在EJBObject中复制一份。例如有一个HelloSessionBean#sayHello(str) 业务,如果要将该业务方法暴露出去给Client使用,与之对应的HelloEJBObject中必然得包含#sayHello(str)方法。也就是说Client需要使用EJBObject来达到与SessionBean交互的。
Home:这个名字起的怪异,我们可以将其理解为一个SessionBean的Factory。EJB容器通过Home对象来创建SessionBean对象,并装配出它的代理对象(EJBObject对象)。这是它的唯一用途。
2、Remote与Local
对于Home,和EJBObject,它们俩个都分为两类:Remote,Local。
Remote模式的,主要用于不在同一个JVM进程里,而在同一个进程里使用时,只需要使用Local模式的即可,这样选择自然是为了性能考虑。
3、Client访问处理流程(很容易看出Local性能好在哪里)
3.1 Remote模式下SessionBean 的访问流程
1、客户端通过JNDI获取到Home对象(EJBHome)的引用
2、客户端使用homeRef#create()方法来创建出EJBObject的Stub。
2.1)客户端底层使用Socket通信将次过程发给服务端Skeleton。
2.2)Skeleton调用服务端的Home对象的create方法,分配SessionBean对象(可能是新创建一个,也可能是从对象池中取一个,具体怎样依赖于是否是Stateful的),同时为该SessionBean对象生成一个代理对象(EJBObject实例),然后返回代理对象的引用。
2.3)客户端拿到EJBObject的引用就是Stub对象。
3、客户端访问业务
3.1) 客户端底层使用Socket通信将次过程发给服务端Skeleton。
3.2)Skeleton根据请求找到该EJBObject,调用与之关联的SessionBean的相应的业务。返回结果
3.3)客户端得到调用结果
3.2 Local模型下SessionBean的访问流程
1、客户端通过JNDI获取到Home对象(EJBLocalHome)的引用
2、客户端使用homeRef#create()方法来创建出EJBLocalObject(怎么创建也要依赖于是否的Stateful的)
3、客户端访问业务
**@Stateless:**标记类把Java类声明为一个无状态会话bean
**@EJB:**表示注入实例,EJB注入和Resource注入相比,EJB注入只是针对于EJB而言,而Resource注入即是对所有的文件都可以进行注入。
**@Remove:**为会话 Bean 声明远程业务接口。用在接口上时,将该接口指定为远程业务接口。在这种情况下,不提供任何 value()。用在方法上,通过这个注解来说明在调用这个方法之后bean的实例将被清除掉。
**@Local:**用在 Bean 类上时,为会话 Bean 声明本地业务接口。用在接口上时,将该接口指定为本地业务接口。在这种情况下,不提供任何 value()。如:@Local(LawsuitService.class)
**@Stateful:**有状态会话 Bean 的组件定义注释。
**@Timeout:**指定无状态会话 Bean 类或消息驱动 Bean 类上接收该 Bean 的 EJB 计时器过期的方法。
**@TransactionAttribute:**在 TYPE-level 应用时,为会话或消息驱动 Bean 的所有业务方法指定默认事务属性。在方法级应用时,仅为该方法指定事务属性。
如:@TransactionAttribute(TransactionAttributeType.SUPPORTS)、
@TransactionAttribute(TransactionAttributeType.REQUIRED)。
**@Interceptors:**声明类或方法的拦截器的有序列表。
**@Lock:**方法声明一个并发锁的单例bean具有容器管理的并发。
**@Schedule(排程器):**计划时间为自动建立一个超时计划基于一个时间表达式。
**@Startup:**标记一个单例在应用初始化期间。
**@ConcurrencyManagement:**声明单例或有状态bean的并发管理类型
1.依赖导入:
pom.xml
javax
javaee-web-api
7.0
provided
2.代码示例:
@Stateless
//不写默认本地@Local
public class ProdMgr {
@EJB//注入prodService,如果出现多个ProdService接口的实现类可以使用name属性区分
private ProdService service;
public String getName() {
String name = service.prod.getName();
return name;
}