EJB3学习总结(1)

Posted on 2009-05-29 22:28 J@mes 阅读(737) 评论(0)  编辑  收藏
作为近期学习EJB3  的一些心得和总结,完全是自己的理解和白话,前辈们请多指教

EJB3学习总结(1)

现状

EJB2得到了较广泛的应用,但真正用对场合的项目不多,那些强调分布式,即业务逻辑和Web是在分布在不同物理层的大型项目。更多得是使用在中小型web应用之上。

EJB3SpringHibernate等一系列轻量级框架运动的发展后现身了,EJB3是基于POJO组件的,同时提供了事务、安全、ORM和分布式等诸多特点,同时AOPDIAnnotation等特性也进一步提高了EJB3的易用性。

EJB3规范

EJB3规范包含3个技术文档:

1.       EJB3 Simplified API

2.       EJB3 Core Contracts & Requirement

3.       Java Persistence API

EJB3组件模型

1.       Session Bean:执行业务服务、控制事务及资源访问

2.       Message Driven Bean:异步调用,通过JMS关联消息队列(Queue)及Topic来响应外部事件

3.       Entity:具有唯一标示的实体,是持久化的基础。

SessionBeanMDBean统称为Enterprise Bean,这点不同于EJB2规范。EntityBean已经划分由持久化Provider去管理和控制,不再由EJB容器管理。

EJB3框架

它提供了对EJB3组件的各种支持,包括容器事务、安全服务、资源池的管理(包括线程池、连接池、实例池)以及组件生命周期的管理、并发支持等。

EJB3的核心features

1.       声明式的元数据:通过Java5AnnotationXML来声明式地去指定Enterprise BeanEntity Bean的行为和特性。如果同时使用两种方式时,XML描述具有更高的优先级。

2.       按异常配置:对于大量可使用default配置的地方都可以省去繁琐的配置,只有需要不按默认行为的才需要显式得通过注解或XML来进行描述。强调用户只有需要配置时才进行配置,可以使代码更为简洁。

3.       良好的可伸缩性:EJB3的实现中在三个方面保证了良好的伸缩性,(1)通过资源池最大程度上对重新对象的重用;(2)使用持久化及缓存避免重复查询和重复创建实体;(3)优化的锁定策略,避免对DB的并发锁定。

4.       JTAJava Transaction API)定义了分布式事务的标准APIEJB容器作为JTA的事务管理器。

5.       通过声明的方式来控制方法级别的访问控制,达到多层安全性。

6.       实体Bean被替换成POJO,简单、轻量,不用再去实现专门的接口,同时可以脱离EJB容器。

7.       SessionBean也更加灵活,不再需要主接口(Home Interface.

8.       依赖注入(dependency injection),可以通过AnnotationXML的方式将依赖数据“推(push)”到bean。例如:将EntityManager注入到SessionBean中,以使会话可以与持久化单元进行交互。

9.       拦截器和回调(Call-back):通过拦截器来完成某些回调方法。

10.   对于SessionBeanMDB,不在需要主方法(ejbCreate()),使用默认构造器来替代。同时也不需要再扩展专有接口。

11.   对于EntityBean,主接口(Home interface)也被替换成EntityManager,后者是一个单例实例工厂,可以管理实体Bean的生命周期。

12.   EJB3的分布式计算模型:EJB3也基于RMI远程服务,远程接口方法按值传递以提供粗粒度的模型。

EJB3角色

1.       定义Enterprise Bean及相关meta-data的三种角色:

(1)       企业Bean提供者(Enterprise Bean provider),负责去定义和实现业务逻辑和结构;负责定义实体的持久化结构及互相关系。

(2)       应用装配者(Application assembler)。

EJB3的会话Bean

EJB3中,SessionBean包括两种类型,Stateful SessionBeanStateless SessionBean

顾名思义,Stateless SessionBean不需维持客户请求的会话状态;而Stateful SessionBean则需要维持特定客户请求的会话状态,同时bean实例也是用客户请求绑定的。

Stateless SessionBean

无状态会话Bean由两个元素组成:业务接口,用来定义所提供的服务;bean类,是对服务接口的实现。注意此处,不需像EJB2.x中分别实现EJBObjectSessionBean接口。

通过示例,通过定义本地接口和(或)远程接口来定义业务接口,这里Local接口和Remote接口的选择遵循一个原则:如果业务的请求者与SessionBean处在同一个JVM中,则可以使用本地接口,反之则必须使用远程接口。

原则上,如果同时使用了本地接口和远程接口,则必须保证二者定义的接口一致,同时由实现的Bean实现这些方法。

无状态会话Bean无需实现EJB特定的接口或扩展类,只需在类级别使用注解——@Stateless即可。同时也在本地接口及远程接口的类级别添加注解——@Local@Remote

通过前面对EJB3特性的介绍,可以知道EJB3DIDependency Injection)的良好支持!在EJB3中,可以将各类资源注入到会话Bean中,这些资源可以是其他的会话Bean、数据源或者是JMS中的队列(Queue)等。要实现依赖注入可以通过添加注解,也可以在XML配置文件中进行描述,但需注意的是,如果二者都进行的配置则以XML文件中的描述为准。

以注解的方式为例,只需添加@Resource注解即可,注入可以通过两种方式:实例变量和setter方法上。

回调(Call-back),通过回调,可以对Bean在其生命周期内各个阶段进行更细粒度的控制和管理。使用回调方法也很简单,回调方法没有多余的限制,只需添加正确的注解即可。

无状态会话Bean两个主要的用于回调方法的注解分别是:@PostConstruct@PreDestroy。其中@PostConstruct的方法会在该bean被实例化后回调执行,但需要注意的是,如果该bean有配置了需要注入的资源,那该回调方法则会紧跟着资源的注入之后而执行。

@PreDestroy的回调方法则是在容器即将销毁bean实例之前被调用,主要用来做一些善后的工作,比如对资源的关闭和清理。(补充,在有状态会话Bean中,该方法是在最后一个带有@Remove注解的方法调用后才被调用,之后容器销毁bean实例。)

另一个关键的元素是拦截器(Interceptor),拦截器的使用也很便捷,通过添加正确的注解即可。拦截器的概念与其他JavaEE的框架或规范中的一致,即拦截业务方法的调用,可以在拦截点附加新的业务逻辑,结合依赖注入特性,可以充分得做到关注点分离(Separation of Concerns)。Enterprise Bean中会话Bean和消息驱动Bean可以定义拦截器方法。

拦截器注解可以添加到方法级别,也可以添加到类级别。被标注的方法在被调用时会被拦截器类拦截,并插队式的先去调用拦截器的方法。对于用到的拦截器类需要添加@Interceptor注解,如果有多个拦截器则使用@Interceptors

@AroundInvoke注解为例,拦截器方法需要关注InvocationContext接口,通过它可以获得被拦截的bean类(Class)、bean中的方法(Method)等,需要强调的是其中的proceed()方法,通过它将拦截请求往后传递,或者到拦截器链中的下一个,或者是结束拦截调用真正的bean方法。

EJB3规范中定义了两种类型的异常,分别是应用异常和系统异常。应用异常是业务逻辑中产生的checked exception;而系统异常则是EJB系统级产生的异常,同时系统异常都是RemoteExceptionRuntimeException的子类,是unchecked exception

有状态会话BeanStateful SessionBean)在特性及细节上与无状态会话Bean很相似。

会话Bean的用户视图

访问会话Bean的用户视图可以有三种形式:

1.       通过Remote接口,远程客户具有位置无关性。

2.       通过Local接口,这两种方式中请求方可以是其他的EJB组件,可以是ServletJSP等。需要注意的是,本地客户具有位置依赖性。

3.       WebService方式,可以将会话Bean发布成为一个WebService,供客户调用。

客户请求会话Bean时,或者通过依赖注入或者通过查找JNDI,来获得会话Beanstub对象,请求是通过stub来进行调用的。对于无状态会话Bean,每次请求将获得新的stub,而有状态会话Bean,则在请求方缓存stub,这样才能使容器知道该返回哪个与客户相关联的bean实例。

通过依赖注入获得会话Bean业务接口的方式是添加注解@EJB,注意要与@Resource区分开。

相比查找JNDI,使用注入的方式会更加简洁,通常对于远程请求使用JNDI更适合。

有状态会话BeanStateful SessionBean

通过实现SessionSynchronization接口,可以在事务点上获得EJB容器的通知:afterBegin,在新事物开始时;beforeCompletion,在事物提交前;afterCompletion,在事物执行完之后。

有状态会话Bean中的回调方法除了PostConstructPreDestroy外,还有PreActivatePrePassivate,分别使用@PreActivate@PrePassivate来注解。

前两个回调方法的细节与无状态会话Bean一致,分别在(1)实例化Bean之后并执行完资源注入后执行;(2@Remove方法执行完毕之后。

对于有状态会话Bean中的@Remove方法,也是一个管理bean生命周期的方法,调用该方法后,容器将会从实例池中将该bean删除。

带有@PrePassivate注解的方法会由EJB容器调用,当某个有状态会话Bean实例长时间空闲,则容器调用该方法将此bean实例钝化,并将状态缓存起来。

当客户请求再次需要使用被钝化的某bean实例时,容器调用该bean@PreActivate方法,返回一个创建好的并带有状态的新实例。

有状态会话Bean的拦截器方法需要注意的是,如果实现SessionSynchronization接口的beanafterBegin始终发生在@AroundInvoke的任何方法前。


只有注册用户登录后才能发表评论。


网站导航: