转载于:http://www.jdon.com/artichect/EJB2_EJB3.html

PS:简单的讲就这三点主要的区别
1.EJB3编程模式简化
引入了IOC(依赖注入)的功能,简化开发代码
2.JPA替代实体bean
java persistence API 替代了EJB2的实体bean;EJB3引入了EntityManger进行需要持久实体的查询、新增、修改。EntityManger类似hibernate
3.引入拦截器
使用jbossAOP来实现拦截器

讲得挺好的,和大家分享下

本文从实战角度比较EJB2和EJB3的异同,通过深入剖析揭示EJB3.0的真相,EJB3.0真是带来简化?还是一种表象上的简化?EJB3.0真的变得轻量了,还是披着羊皮的狼?

EJB编程模型的简化

  首先,EJB3简化的一个主要表现是:在EJB3中,一个EJB不再象EJB2中需要两个接口一个Bean实现类,虽然我们以前使用JBuilder这样可视化开发工具自动生成了EJB2的这三个类,好像不觉得复杂,但是当EJB个数增加时,就显得累赘了。

  简化后的EJB3的sessionBean依靠annotations元注释来定义SessionBean的类型,也就是说,EJB2中的SessionBean类型区分在EJB3继续继承,只不过书写代码的方式不同而已,例如下代码使用@Stateless表示一个无状态Bean。

package example;

@Stateless
public class TestSessionBean implements TestSessionLocal{
public void xxxx(){

    System.out.println("hello");  

  }

}

  上述Session Bean中没有了EJB2中ejbCreate等多余方法,这样TestSessionBean很象一个普通JavaBeans了。是不是简单?先别急,我们需要接着看看这个TestSessionBean是如何调用?

  在EJB2中,一个EJB对象的调用需要经过两个步骤:JNDI寻找和工厂创建,如下例:

Context ctx = new InitialContext(); 
TestSessionLocalHome home = (TestSessionLocalHome)ctx.lookup("java:comp/env/ejb/TestSession");
TestSessionLocal bean = home.create();

bean.xxxx();//真正目的 对象使用

  其实上述代码最后一句才是我们真正目的,但是为了这个目的,必须经过前面冗长的代码创建,而在EJB3中,为创建型模式的Ioc模式(或称依赖注射)取代了home.create这样简单工厂创建模式,以一种更加松耦合和简洁的方式解决了对象创建问题,可以让我们精力更集中在对象的使用上了。

  下面是annotations+Ioc/DI的EJB3调用代码:

@EJB //注意这里后面是空白 
private TestSessionLocal testbean; //使用接口声明

public void invoke(){ 
  testbean.xxxx(); //直接使用

}

  上述EJB3调用代码中,@EJB后面是空白,这其实使用了TestSessionLocal的缺省JNDI名称,一直到这里,我们一直满足于EJB3的简化,但是如果研究@EJB语法后,会发现其完整写法如下:

@EJB(
name = “ejb/shopping-cart”,//被调用者Cart实现类的ejb-reference名称
beanName = “cart1”, //被调用者的名称 beanName
beanInterface = ShoppingCart.class, //接口名称 
description = “The shopping cart for this application”
)
private Cart myCart;

  上述完整@EJB写法适用于同一个接口有多个实现子类时,其中关键是 beanName的定义:beanName是被调用EJB的类名 (不带包名,称为unqualified name ),或者, 如果被调用EJB有 XML descriptor定义, 它就是配置项ejb-name值(如果你使用过EJB2,就容易理解这个ejb-name了)。

  @EJB还有一个属性mappedName,这是被调用者的JNDI名称,一般不使用,因为这个JNDI名称和具体服务器有关,如果是JBoss4,那么它的缺省形式是:"EAR-FILE-BASE-NAME/BEAN--CLASS-NAME/local" (or remote). 也就是:被调用者EJB所在EAR包的名称/Bean实现子类(不带包名)/local,如果是remote调用,就是remote。 如果这个EJB被打包在jar包中,那么JNDI名称就是EJB-CLASS-NAME/local and EJB-CLASS-NAME/remote,当然,作为替换@RemoteBinding 和 @LocalBinding 也可定义JNDI名称。

  也就是说:JBoss的EJB3中,如果你不使用XML配置,直接使用annotations,那么JNDI缺省名称没有一个统一规定名称,有的可以直接是类名;在JBoss中还和EJB打包的形式有关,是动态变化的。如果你以为在EJB3中不会接触到这个变化的JNDI缺省名称,那你就错了。

  JBoss 4 在Servlet中不支持类似EJB调用EJB那样的依赖注射 binding-by-injection,因为Web容器和EJB容器是两个不同容器,当然借助另外JBoss Seam则是另外一回事,因此,在Web层调用EJB,就必须通过JNDI绑定一个session bean,这时,你就必须使用到那个变化不定的缺省JNDI名称了。 

JNDI Naming Context

  无论J2EE还是Java EE中,JNDI是一个好像不起眼,但是极其重要的概念,不理解JNDI可以说,对J2EE或JavaEE只了解一半。

  JNDI本来是EJB2中比较复杂的一个概念,不同容器有自己的JNDI名称,由此EJB2引入了第三者EJB-Reference,虽然解决了代码中耦合JNDI名称问题,但是又带来了更加烦琐的配置,这种现象当然被JavaEE5.0继续继承了下来,问题远非这么简单。

  J在Java EE5.0中(包括EJB3和Web环境),当我们需要访问一个JNDI环境下资源时,有两种方式:除了传统EJB2中的JNDI调用方式;还有一种就是:使用依赖注射Ioc模式,这个依赖注射的表达方式是使用annotations。

  因此,在EJB3中,必须好好搞清楚annotations、依赖注射和JNDI之间的关系,如果这个问题不弄明白,EJB3就绝非EJB2那么容易搞定,当然,搞定了的结果很简单,让人感觉简化轻量了,真不知道EJB3这种简化是不是有点象”掩耳盗铃“。

  可以总结一句:凡是EJB2中使用配置文件定义的;EJB3一般都可以使用 annotations定义(当然EJB3也支持配置文件定义);凡是EJB2通过JNDI寻找的资源(调用容器中其他EJB、调用环境变量等Resource资源等),都是可以依靠annotations+依赖注射机制完成。

JPA替代实体Bean

.   如果说EJB3与EJB2变化最大的部分,就是持久层使用Java Persistence API 替代了EJB2的实体Bean,这样,我们通过Evans DDD建模得到的Domain Model类可以直接持久化保存到数据库,不像EJB2中还需要在Model类和实体Bean中进行一次转换。

  EJB3引入EntityManager进行需要持久实体的查询及其新增修改;EntityManager非常类似JDBCTemp/HibernateTemplate等持久化模板。

  JPA和JDO以及Hibernate等O/R mapping框架都是非常相似的。

  虽然在JPA中,我们都可以使用Annotation来替代配置,实现很多过去需要专门配置文件才能实现功能,不再一定需要 每个服务器不同的cmp映射文件,增强了移植性,但是EJB3还是需要 一个叫persistence.xml配置文件,在这个配置中进行数据库JNDI配置;当然,还有一些和具体服务器有关的配置属性,如果使用JBoss,JBoss的JPA底层使用Hibernate实现,因此在persistence.xml要进行有关Hibernate属性配置:

<persistence>
  <persistence-unit name="Ejb3Tutorial"> 
    <jta-data-source>java:/TestDS</jta-data-source> 
    <properties> 
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/> 
    </properties>
  </persistence-unit>
</persistence>

拦截器概念

  EJB3.0引入了类似AOP中的拦截器概念(注意,AOP不只等于拦截器,所以不能认为EJB3就是完全AOP了),JBoss使用JBossAOP来实现拦截器功能,自己定义的拦截器方法可以拦截任何一个业务方法或生命周期事件回调;拦截方法可以在bean中定义或专门的拦截器类。

@Stateless
@Interceptors( { NullChecker.class, ArgumentsChecker.class })
public class StatelessSessionBean implements StatelessSession {

  // This business method is called after
  // the above two interceptor's @AroundInvoke
  // methods are invoked. Hence it is guaranteed
  // that the argument to this method is not null
  // and it starts with a letter
  public String initUpperCase(String val) {
    String first = val.substring(0, 1);
    return first.toUpperCase() + val.substring(1);
  }

}

  NullChecker和ArgumentsChecker是StatelessSessionBean两个拦截器,在拦截器NullChecker中,必须指定的拦截方法为@AroundInvoke。

public class NullChecker {

  @AroundInvoke
  public Object checkIfNull(InvocationContext ctx)
        throws Exception {
      Method method = ctx.getMethod();
      if (method.getName().equals("initUpperCase")) {
        String param = (String) (ctx.getParameters()[0]);
      }
       .........

      }
       // Proceed to the next interceptor
      return ctx.proceed();
  }

}

总结

  总之,从上面EJB2和EJB3的总结上看,EJB3.0在EJB2基础上,引入了更多概念,最大变化就是Annotation替代了配置文件,对于一些配置文件厌恶者来说,是一个好事;但是在实战中,在一些依赖注射不能照顾到地方,我们还必须和更加复杂的JNDI名称打交道,这恐怕是EJB3的一个不是很完美的地方。

  关于EJB3中可测试性的优点被很多人津津乐道,将EJB脱离容器测试,虽然可以进行微观的单元测试,但是脱离容器就是脱离特定完整的业务场景,所以,基于容器的(也就是基于完整的业务场景)单点跟踪调试才是最重要的,这些必须依赖开发工具的发展,目前已经在Eclipse3.2以后版本+WPT(或JBossIDE/Lomboz)中实现,这个功能适合大部分J2EE/JavaEE程序。

  所以,板桥个人对脱离容器的测试要求并不以为然,而这个曾经是Martin Fowler定义POJO的主要内容,因为在过去容器概念刚刚出现时,很多人都有容器恐惧症,以为容器都是不透明的,我们的业务对象放入进去,就失去了控制,这些都是落后设计观念导致,其实,Java语言本身提供的可跟踪性和介入性是非常强大,目前性能跟踪工具Profiler可以在容器运行时,跟踪到容器中某个具体类占据CPU多少,占用多少内存资源,那么一个单点调试岂是一个个所谓容器可以阻挡的?容器是Java语言的特点,ClassLoader决定了Java就是一个容器性的语言,关键这个容器是必须透明的。

EJB3与EJB2架构对比相关推荐

  1. EJB2与EJB3架构对比

    今天在写一个ejb时遇到个怪事,在调用ejb home 生成对象的时候,总是抛出ClassCastException,仔细查了下代码,发现没发现什么问题,这让我很费解,调试许久后无意中发现由于配置经过 ...

  2. AI芯片:寒武纪DianNao,英伟达NVDLA和谷歌TPU1的芯片运算架构对比分析

    前面几篇博客分别分析了目前市面上能够找到的各家AI芯片的结构. 下面做一个阶段性的对比分析及总结. AI芯片运算架构对比 整体来看,NVDLA的架构与寒武纪的DianNao比较像.所以,单位资源的性能 ...

  3. X86、NP、ASIC、MIPS架构对比,存储

    X86.NP.ASIC.MIPS架构对比_weixin_34390105的博客-CSDN博客 为什么MIPS架构的路由器CPU能实现比X86高很多的网络吞吐量? - 知乎 ASIC芯片_百度百科 (b ...

  4. DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析)、使用方法(NLP领域/CV领域)、案例应用之详细攻略

    DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析).使用方法(NLP领域/CV领域).案例应用之详细攻略 目录 Transfo ...

  5. 实时数仓 Kappa 架构与 Lambda 架构对比,优缺点有哪些?

    实时数仓 Kappa 架构与 Lambda 架构对比,优缺点有哪些? 1 数据仓库概念 2 离线大数据架构 3 Lambda 架构 4 Kappa 架构 5 Lambda 架构与 Kappa 架构的对 ...

  6. Android与iOS系统架构对比

    1.  引言 自iPhone在07年初次登台将智能手机直接带向移动互联时代后,一方面智能手机普及率直线上升,另一方面整个市场目前呈现了iPhone与Android手机两强争霸的局面. iOS是由苹果公 ...

  7. ARM与X86 CPU架构对比区别

    ARM与X86 CPU架构对比区别 CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法.早期的CPU全部是CISC架构,它的设计 ...

  8. FPGA异构计算架构对比分析

    FPGA异构计算架构对比分析 ▌本文来源:智能计算芯世界(已授权) AI芯片主要分为CPU .GPU.FPGA以及ASIC.其中以CPU.GPU.FPGA.ASIC的顺序,通用性逐渐减低,但运算效率逐 ...

  9. 各大厂分布式链路跟踪系统架构对比

    随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务.消息收发.分布式数据库.分布式缓存.分布式对象存储.跨域调用,这些组件共同构成了繁杂的分布式网络,那现在的问题是 ...

最新文章

  1. Mybatis优缺点
  2. Linux笔记:vim
  3. 并行程序设计(MPICH环境配置)win10
  4. java.lang.NoSuchFieldError: EMPTY_ORDERED_ITERATOR起因及解决办法
  5. Java poi读取,写入Excel2003
  6. 【JOURNAL】康生篆书联
  7. 王益:分布式机器学习的故事
  8. OpenCasCade将鼠标点映射到OCC三维视图中的三维点(鼠标点转换为OCC三维坐标)
  9. oracle基础教程(第四天)数据库管理
  10. 听音扒谱app_掌握这些,你也可以轻松扒谱(下)
  11. 新版itunes不显示图书_告别 iTunes!苹果新版mac操作系统正式上线,12大升级亮点解读...
  12. Python学习笔记—— 面向对象1. 面向对象基础
  13. 软件著作权 php代码行数,申报软件著作权时,如何快捷计算源码行数
  14. 联邦学习FATE社区2021年度生态峰会倒计时1天,请查收这份参会攻略
  15. 2018年第九届蓝桥杯大赛软件类省赛C/C++B组参赛感想
  16. 文献阅读笔记 《具有目标定位和边界保持的基于个人注视的目标分割》
  17. Python:PIL库中getpixel()-方法的使用
  18. 计算机等级二级c语言英文,计算机等级考试二级C语言考试大纲(国外英文资料).doc...
  19. 国产操作系统Office哪个好用?6款工具推荐!
  20. WinHex数据恢复新手入门

热门文章

  1. 概率论与数理统计(学习笔记)——平平无奇的知识点
  2. STC15系列PWM中断控制寄存器介绍以及PWM相关示例
  3. Activity传递数据四种方法
  4. 激光SLAM从理论到实践学习——第四节(激光SLAM的前端配准方法)
  5. 知乎问答应该怎么做?
  6. edge浏览器启动页面修改后依然跳转到其他网页
  7. 小板匹配 从上层到下层
  8. Python+Selenium 自动化测试 2. Webdriver API介绍
  9. RabbitMQ安装教程及使用
  10. nginx 防止恶意域名解析_nginx防恶意域名解析