EJB2和EJB3在架构上的不同点


Posted in 面试题 onSeptember 29, 2014
EJB编程模型的简化

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

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

package example;@Statelesspublic 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();//真正目的 对象使用

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属性配置:

java:/TestDS

拦截器概念

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 letterpublic String initUpperCase(String val) {String first = val.substring(0, 1);return first.toUpperCase() + val.substring(1);}}

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

public class NullChecker {@AroundInvokepublic 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 interceptorreturn 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中,为创建型模式的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”, //被调用者的名称 beanNamebeanInterface = 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+依赖注射机制完成。

Tags in this post...

面试题 相关文章推荐
如何用PHP实现邮件发送
Dec 26 面试题
Yahoo的PHP面试题
May 26 面试题
介绍下Java的输入输出流
Jan 22 面试题
strstr()的简单实现
Sep 26 面试题
什么是事务?事务有哪些性质?
Mar 11 面试题
叙述DBMS对数据控制功能有哪些
Jun 12 面试题
请解释在new与override的区别
Oct 29 面试题
STP协议的主要用途是什么?为什么要用STP
Dec 20 面试题
Linux常见面试题
Mar 18 面试题
中间件分为哪几类
Mar 14 面试题
UNIX命令速查表
Mar 10 面试题
J2EE面试题
Mar 14 面试题
比较一下entity bean和session bean
Dec 27 #面试题
介绍一下RMI的基本概念
Dec 17 #面试题
JSP和EJB可以共享HttpSession么?EJB里面可以改变session里面的内容
Jun 05 #面试题
敏捷开发的主要原则都有哪些
Apr 26 #面试题
什么是规则表达式
May 03 #面试题
软件设计的目标是什么
Dec 04 #面试题
设计模式的基本要素是什么
Apr 21 #面试题
You might like
让你的WINDOWS同时支持MYSQL4,MYSQL4.1,MYSQL5X
2006/12/06 PHP
ThinkPHP 3.2 版本升级了哪些内容
2015/03/05 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
Javascript与flash交互通信基础教程
2008/08/07 Javascript
jquery让指定的元素闪烁显示的方法
2015/03/17 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
深入解析JavaScript中的数字对象与字符串对象
2015/10/21 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
JS代码实现table数据分页效果
2016/05/26 Javascript
深入理解jQuery.data() 的实现方式
2016/11/30 Javascript
AngularJS Controller作用域
2017/01/09 Javascript
JavaScript数据类型和变量_动力节点Java学院整理
2017/06/26 Javascript
强大的JavaScript响应式图表Chartist.js的使用
2017/09/13 Javascript
Vue 自定义标签的src属性不能使用相对路径的解决
2019/09/17 Javascript
npm qs模块使用详解
2020/02/07 Javascript
Python标准库之sqlite3使用实例
2014/11/25 Python
使用SAE部署Python运行环境的教程
2015/05/05 Python
在Python的Django框架中获取单个对象数据的简单方法
2015/07/17 Python
使用Python的Tornado框架实现一个Web端图书展示页面
2016/07/11 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
Python 用Redis简单实现分布式爬虫的方法
2017/11/23 Python
学习Python3 Dlib19.7进行人脸面部识别
2018/01/24 Python
用Python实现二叉树、二叉树非递归遍历及绘制的例子
2019/08/09 Python
基于Python爬取爱奇艺资源过程解析
2020/03/02 Python
Jupyter notebook 启动闪退问题的解决
2020/04/13 Python
python设置表格边框的具体方法
2020/07/17 Python
Python实现快速大文件比较代码解析
2020/09/04 Python
桥梁与隧道工程专业本科生求职信
2013/10/08 职场文书
新闻专业大学生找工作的自我评价
2013/10/30 职场文书
行政管理专业推荐信
2013/11/02 职场文书
研究生毕业鉴定
2014/01/29 职场文书
毕业生自荐书
2014/02/03 职场文书
人力资源管理求职信
2014/08/07 职场文书
党的群众路线教育实践活动批评与自我批评范文
2014/10/16 职场文书
2014年工作总结与下年工作计划
2014/11/27 职场文书
消防宣传语大全
2015/07/13 职场文书