EJB = Enterprise Java Bean,它和JavaBean有本质的区别,最好不要将他们混淆起来,就像不要将Java和 
Javascript混淆起来一样。EJB有3中类型:Session, Entity和Message-driven。EJB2.x使用起来很复杂, 
这些缺点在EJB3.0已经不存在了。http://blog.csdn.net/pathuang68/archive/2009/04/19/4091645.aspx这里有怎样开发EJB的详细教程,说到JavaBean和EJB的区别,我们可以这么说,他们几乎没有什么是相同的,如果非要说有什么区别的话,那就是: 
1. JavaBean的使用可以不需要容器,EJB的运行一般需要EJB容器(即应用服务器,如JBoss/Weblogic/Websphere...等等) 
2. EJB可以使用JavaBean,尤其是Entity EJB的时候,但几乎没有看到JavaBean可以使用EJB的。

说说 WebService在 开发中的运用。 
1. WebService由于采用http协议,而且使用和web服务相同的端口(如80),因此它可以不受防火墙的限制 
2. WebService由于采用了XML做传输载体,因此它对所有的编程语言来说都是中性的,也就是说,不同的编程语言可以通过WebService进行通讯 
3. 也正因为WebService采用XML做传输载体,由于XML中存在很多标记(就像HTML中的 <html>之类的东西),因此通信效率相对比较低。 
4. 以前Webservice的通信,在网络上传输的时候不是很安全,现在这些都已经解决,如MS的WSE,当然也可以自己写代码来保证安全。 
5. Webservice出现之初,由于采用XML进行传输,因此传输二进制文件如图片就存在问题,解决办法是首先将图片文件进行诸如Base64之类的编码,传输到接收端后,再有接收端进行反编码,从而得到二进制文件。

DCOM 与COM的区别 
1. COM不支持分布式通讯,而DCOM(Distributed COM)支持 
2. COM的运行不需要容器,而DCOM需要,如MTS 
3. COM可以通过工具转换成DCOM 
4. COM和DCOM有点过时,但目前仍有很多应用在使用他们

JavaEE方面我都会做开发。但不太理解如何利用。 
JavaBean(SSH) VS EJB 
这个问题我觉得改成SSH vs. EJB可能更合适一点。SSH = Spring + Struts + Hibernate,他们组合起来可以实现和EJB类似的功能。但一般情况下SSH应用与小型项目,EJB通常用于较正式的、大型的项目。比如想象中国移动这样的公司可能会用Weblogic或者Webshpere,即使用EJB,而不会采用SSH,其中一个很重要的原因是SSH都是开源框架,没有专门的技术服务支持,当然还有一些其他原因。 
EJB Vs WebService。 
1. 他们的通信方式不同。EJB采用的是IIOP的机制,Webservice用的就是http 
2. EJB仅限于Java应用之间的通信,Webservice的通信可以跨语言 
3. EJB通信的效率要比Webservice要高 
4. EJB也可以部署成Webservice

JavaBean Vs COM 
两者之间没有太大的可比性。COM的原理是非常复杂的(如果感兴趣,可以去研究一下MSDN相关技术文档),JavaBean如前面所说是非常简单的。

EJB Vs DCOM 
这两个东西的确比较类似,它们运行都需要容器EJB需要诸如Weblogic,Webshpere以及JBoss这样的EJB容器,DCOM的容器则是MTS,他们都可以进行分布式计算。不过DCOM目前已经逐渐被COM+代替,不过而开发和部署人员来说DCOM和COM+的过渡是相当平滑的。

DCOM/COM+是Microsoft的技术,EJB是SUN的技术,EJB被支持的基础更广泛一些,著名的厂家如IBM,Oracle等等如支持EJB,这主要是因为EJB得益于Java是开源的缘故。

 
   

EJB是Enterprise Java Bean的简称,翻译后应该是:企业级Java组件,也可以称为分布式组件。它是为分布式商业服务提供了一个思想超前的、提供了安全和事务的、通用的平台。

2、EJB体系结构

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()。

3、SessionBean

它是对业务逻辑的封装,类似于我们经常写的Service层。它可以以local, remote, webservice 服务的方式被client调用。

3.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对象)。这是它的唯一用途。

3.2 Remote与Local

对于Home,和EJBObject,它们俩个都分为两类:Remote,Local。

Remote模式的,主要用于不在同一个JVM进程里,而在同一个进程里使用时,只需要使用Local模式的即可,这样选择自然是为了性能考虑。

Home、EJBObject我们看到的只是接口,谁来创建他们呢?

这个问题其实很简单了,之前已说了EJBObject是一个Proxy,我们不难想到,基于动态代理或者字节码技术,就可以动态的(具体来说就是部署EJB时)生成Home、EJBObject的实现类。

此外,在构建完Home的实现类之后,就会创建出一个单例的Home对象,并将其注册到JNDI服务器上。这样客户端就可以通过jndi服务lookup到该Home的引用。

EJBObject对象,是在client通过EJBHome#create() 或者EJBLocalHome#create()时由服务端的Home对象创建一个EJBObject的实例,并返回它的引用给客户端。

3.3 Client访问处理流程

在上面已经说明Home对象在ejb应用部署时就会创建出一个单例,并注册到JNDI服务器上。

客户端访问一个业务的流程是怎样的呢?

3.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.3.2 Local模型下SessionBean的访问流程

1、客户端通过JNDI获取到Home对象(EJBLocalHome)的引用

2、客户端使用homeRef#create()方法来创建出EJBLocalObject(怎么创建也要依赖于是否的Stateful的)

3、客户端访问业务

很容易对比出Local模式性能好在哪了。

在EJB3 中,会有更方便的写法了,用@EJB即可搞定。

3.4 基于EJB2.1的Demo

1)编写业务接口 AdviceService

public interface AdviceService {
String getAdvice(String str) throws RemoteException;
}

2) 编写SessionBean类

public class AdviceServiceImpl implements AdviceService, SessionBean {
public String getAdvice(String str){
return “Advice” + str;
}
// 其他的ejbCreate,ejbActivate等不展示
}

3)指定EJBObject接口

public interface AdviceServiceEjbObject extends EJBObject, AdviceService{
}

4) 指定Home接口

public interface AdviceServiceFactory extends EJBHome{
public AdviceServiceEjbObject create() throws RemoteException, CreateException;
}

5) 在ejb-jar.xml中配置要暴漏的SessionBean:

ejb-jar.xml是放在META-INF目录下。

6)关联到jndi服务

这一步是WebLogic服务器上配置的,其他的JavaEE服务器应该也有类似的机制。

7)打包部署到JavaEE服务上。

8)客户端调用

代码中的JndiResources.getProperty(“ejb.advice”) 用于取得 xxx.properties文件中配置的JNDI名称,这个JNDI名称,就是第6步映射的JNDI名称。EjbEnvs.getEjbEnv()方法,是为了得到在不同的JavaEE服务器上的InitialContext的配置,这属于测试用例的配置。

例如:

然后就是通过JNDI获取的Home Reference,然后调用create获取EJBObject的Stub,最后调用业务方法。

3.5 SessionBean 分类

在上面说的通过Home对象的create过程中,有个SessionBean创建,是要依赖于是否是Stateful的。也就是说SessionBean会区分为:Stateless, Stateful,在EJB3.1加入Singleton的。

3.5.1 Stateful SessionBean

对于一个普通的Java对象而言,它的属性就是它的状态。而Stateful SessionBean是与Client相关联的,也就是说一个Client会有一个SessionBean与之对应。这样的SessionBean可以存活在与Client的整个会话期间。当一个Client终端时,SessionBean才会与该Client失去联系。

SessionBean的state(也就是对象的字段)会在整个会话期间保留,直到会话关闭。

3.5.2 Stateless SessionBean

无状态的SessionBean,它的state只会存在于业务方法调用期间,一旦方法调用完毕,这些字段就会失效。无状态的SessionBean不会与某个Client关联。

3.5.3 Singleton SessionBean

单例的SessionBean,那么对于一个应用,只会存在一个这样的对象。它是可以被多个Client并发的调用的。Stateful、Stateless SessionBean,在同一时间都只能为一个Client服务,它们是采用对象池技术实现的。

Stateful

Stateless

Singleton

与Client关联

单个实例支持并发访问

对象管理

LRU等缓存

对象池

单例

发布为WebService

存活周期

整个会话

单个业务方法调用

应用

单个实例被多个Client重用

不会

可以

可以

3.6 SessionBean 生命周期

3.6.1 Stateful SessionBean

对于Stateful SessionBean。当Client通过Home Ref执行create时,服务端的Home会直接创建一个代理对象(EJBObject/EJBLocalObject实例),和一个SessionBean(会被EJB容器决定是否作为钝化状态)。

图中上边的:1)2)3)4)分别代表了:

1) SessionBean 对象的创建

2) 依赖注入

3) 执行@PostConstruct

4) 执行init方法、或者ejbCreate方法。

此时对象创建完毕,bean变为ready状态,也会返回给client一个proxy的stub。但EJB容器仍然要对这个SessionBean的状态定期进行处理,通常会基于LRU缓存对cache中bean进行passivate处理。Passivate之前、activate之后会有相应的回调方法执行。

图中下边的1)2)代表了:

1) Client调用@Remove

2) 服务端调用@PreDestory

之后一个SessionBean就被销毁了,等待它的将是JVM的GC。

3.6.2 Stateless SessionBean

对于Stateless SessionBean,当Client使用Home Ref创建EJBObject(或者EJBLocalObject)对象时,并不会创建一个关联的Session Bean。当调用业务时,才会从SessionBean Pool选择一个空闲的处理业务。它是不存在passivate, activate的转换的。

3.6.3 Singleton SessionBean

上文说了,它的生命周期在整个应用期间。

4、EntityBean

可以把EntityBean看做是数据库记录。数据库的访问才用JPA(Java Persistence Abstract,参见javax.persistence.*)

分为CMP(Container managed Persistence),BMP (Stateless SessionBean managed Persistence)两种,他们支持事务(声明式事务、编程式事务)

事务支持扁平式事务,嵌套式事务。学过Spring的人应该都了解的,相信Spring的作者肯定对EJB了解极深。

5、MessageDrivenBean

在前面已经说明,他就是一个MessageListener。

前文已经说明了一切。这里只说一下MessageDrivenBean的生命周期:

6、EJB vs Spring

网上充斥着大量的EJB已死、Spring替代EJB的文章。我就纳闷了,EJB是做分布式业务调用的,Spring是做IOC的,两者有什么可比的呢?这是我在了解EJB之前的一个疑问。

通过对EJB做了个简单的了解,我终于知道他们在比什么了:

AOP & IOC

通过上面对EJB的阐述,我们从Bean的生命周期中,我们可以看到,EJB容器可以说是IOC的先驱。在后续的版本中EJB已经补齐了IOC的支持。

EJB中对SessionBean调用之前,还有做一些其他事情, 譬如Security、Transaction。这完完全全就是AOP的应用嘛。

通过上面的例子知道,要部署一个EJB组件,确实挺麻烦的,还要写那么多程序化的接口(Home和EJBObject)。EJB3.0之后支持了注解,释放了这个繁琐的过程。也就是说EJB的笨重,应该是Spring等一大批IOC容器(Spring,Guice,HK2)产生的原因了。

只能说EJB在某些场合(Local模式下)下被Spring替代。

Java系列之EJB 理解的更多相关文章

  1. 为什么你学不会递归?告别递归,谈谈我的一些经验 关于集合中一些常考的知识点总结 .net辗转java系列(一)视野 彻底理解cookie,session,token

    为什么你学不会递归?告别递归,谈谈我的一些经验   可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了! ...

  2. 多线程系列之 java多线程的个人理解(二)

    前言:上一篇多线程系列之 java多线程的个人理解(一) 讲到了线程.进程.多线程的基本概念,以及多线程在java中的基本实现方式,本篇主要接着上一篇继续讲述多线程在实际项目中的应用以及遇到的诸多问题 ...

  3. 【转】O'Reilly Java系列书籍建议阅读顺序(转自蔡学庸)

    Learning Java the O'Reilly's Way (Part I) Java 技术可以说是越来越重要了,不但可以用在计算机上,甚至连电视等家电用品,行动电话.个人数字助理(PDA)等电 ...

  4. Java系列笔记(2) - Java RTTI和反射机制

    目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这 ...

  5. Java系列笔记(4) - JVM监控与调优

    目录 参数设置收集器搭配启动内存分配监控工具和方法调优方法调优实例     光说不练假把式,学习Java GC机制的目的是为了实用,也就是为了在JVM出现问题时分析原因并解决之.通过学习,我觉得JVM ...

  6. Java系列笔记(3) - Java 内存区域和GC机制

    目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...

  7. Java系列笔记(1) - Java 类加载与初始化

    目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个 ...

  8. Java系列笔记(6) - 并发(上)

    目录 1,基本概念 2,volatile 3,atom 4,ThreadLocal 5,CountDownLatch和CyclicBarrier 6,信号量 7,Condition 8,Exchang ...

  9. 【转载】Java系列笔记(1) - Java 类加载与初始化

    Java系列笔记(1) - Java 类加载与初始化 原文地址:http://www.cnblogs.com/zhguang/p/3154584.html 目录 类加载器 动态加载 链接 初始化 示例 ...

随机推荐

  1. String类和StringBuilder

    1,首先,明确一点,String对象是不可变的,这个不可变的意思是说:任何看起来修改String值的方法,实际上都是创建了一个新的String对象. 2,String对+号操作符进行了重载,而这个重载 ...

  2. 关于fork()父子进程返回值的问题

    我们都知道,父进程fork()之后返回值为子进程的pid号,而子进程fork()之后的返回值为0.那么,现在就有一个问题了,子进程fork()的返回值是怎么来的?如果子进程又执行了一遍fork()函数 ...

  3. 第二百零二节,jQuery EasyUI,Layout(布局)组件

    jQuery EasyUI,Layout(布局)组件 学习要点: 1.加载方式 2.布局属性 3.区域面板属性 4.方法列表 本节课重点了解 EasyUI 中 Layout(布局)组件的使用方法,这个 ...

  4. JAVA的protected权限

    1.派生类能够訪问父类的protected数据.这是毫无疑问的. 2.今天做Think in java的习题发现,同一个包内的一个类调用还有一个类的protected数据是能够的.代码例如以下: pa ...

  5. hdu 1078 FatMouse and Cheese【dp】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:每次仅仅能走 横着或竖着的 1~k 个格子.求最多能吃到的奶酪. 代码: #include ...

  6. 在EntityFramework(EF)中删除主从表记录

    删除主表:  如果要删除单个的Book对象,由于启用了级联删除,干掉一个Book,它所关联的所有BookReview也一并删除了. (说的简单,如果用Attach方法或者Remove,加修改删除状态, ...

  7. diango-tinymce富文本编译器

    应用到项目中 在settings.py中为INSTALLED_APPS添加编辑器应用 INSTALLED_APPS = ( ... 'tinymce', ) 在settings.py中添加编辑配置项 ...

  8. veridata实验举例(4)验证veridata查找出updata、delete操作导致的不同步现象

    veridata实验举例(4)验证veridata查找出updata.delete操作导致的不同步现象 续接:<veridata实验举例(3)验证veridata查找出insert操作导致的不同 ...

  9. Android开发:《Gradle Recipes for Android》阅读笔记(翻译)4.2——增加自定义task

    问题: 你想要在整体的构建过程中加入自定义的task. 解决方案: 使用dependOn属性将你的任务插入 directed acyclic graph 讨论: 在初始化阶段,Gradle将任务根据依 ...

  10. linux下jmeter使用帮助

    1.linux下jmeter使用方法 例:jmeter -n -t test1.jmx -l logfile1.jtl -H 192.168.1.1 -P 8080 -h 帮助 -> 打印出有用 ...