`
longgangbai
  • 浏览: 7339216 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[转]EJB3.0中的依赖注入,截获器及其在WebLogic Server 10中的扩展

阅读更多

1 前言

  与EJB2.1相比,EJB3.0规范引入了两个重要概念:依赖注入(DI:Dependency Injection)和截获器(Interceptor),本文首先介绍了这两个概念并给出相关示例,然后分析了EJB3.0规范在这两方面的不足之处,最终深入探讨了WebLogic Server 10对它们的支持和扩展。

2 依赖注入

  2.1 基本概念

  依赖注入是从开源社区的一些著名轻量级容器(如Spring、Pico container)中所发展出来的概念,其主要思想就是由容器而不是对象本身来负责处理对象之间的依赖关系。与传统的服务定位器相比,依赖注入具有易测试、弱侵入性等优点,这也就是为什么在最新的Java EE 5规范中引入它的原因。

  对于EJB3.0来说,依赖注入就是由容器负责查找被依赖的对象并注入到依赖bean中,而bean本身不再需要进行JNDI或者context查询。此外,依赖注入发生在任何业务方法被调用之前,而且支持setter方法注入和域注入两种方式。

  通过与标注结合使用,在bean类中声明依赖注入是非常简单的(当然,也可以在部署描述符文件中声明依赖注入):

    @EJB用于注入EJB业务对象
    @PersistenceUnit 用于注入EntityManagerFactory
    @PersistenceContext 用于注入EntityManager
    @Resource 用于注入其它资源对象,如连接工厂、消息目标等

  2.2 示例

@Stateless
public class ServiceBean implements Service {
private javax.sql.DataSource myDS;
@Resource(mappedName=“LocalDataSource")
public void setMyDS(javax.sql.DataSource ds) {this.myDS = ds; }
@EJB(beanName=“AccountBean")
private Account account;
}

  在无状态会话bean ServiceBean中,声明了两个依赖:一个是数据源,一个是业务接口。在运行期间,EJB3.0容器一旦创建了ServiceBean的实例,就会分别通过方法注入和域注入将数据源对象和业务对象注入到ServiceBean中。

3 截获器

  3.1 基本概念

  作为EJB3.0中提出的新概念,截获器是可以对bean的业务方法和生命周期事件进行拦截的组件。截获器需要由@Interceptors 或发布描述符文件中相关的标签指定。截获器可以带有状态而且可以进行依赖注入,其生命周期与其所绑定的EJB bean实例的生命周期一致。

  定义在截获器中用于拦截目的的方法被称为截获器方法,其中,针对业务方法的截获器方法通过@AroundInvoke标注或发布描述符文件中相关的标签指定;针对生命周期回调的截获器方法通过@PostConstruct, @PreDestroy等标注或发布描述符文件中对应的标签指定。

  截获器分为四类:

    缺省截获器:可作用于ejb-jar中定义的所有EJB bean。缺省截获器只能定义在DD中,不存在相应的标注
    类级截获器:只能作用于所指定的EJB bean
    方法级截获器:只能作用于所指定的某个EJB bean业务方法,方法级截获器不能用于拦截bean的生命周期事件
    bean 级截获器:又被称为自我截获器,因为截获器同时就是EJB bean本身,此时相关的截获器方法只能作用于该EJB

  3.2 截获器链的调用顺序

  因为可以为EJB定义多个截获器,所以存在截获器链的调用顺序问题,缺省情况下,以下原则被遵循:

    调用顺序依次是缺省截获器、类级截获器、方法级截获器以及bean级截获器
    对于同类别的截获器,按照声明的顺序调用
    总是优先调用父类的截获器方法。

  此外,EJB3.0规范还提供了更灵活的选项,详细信息请参考EJB3.0规范中“截获器”一节:

    在发布描述符文件中设置“exclude-default-interceptors” 可以取消对缺省截获器的调用,而应用“exclude-class-interceptors”则取消对类级截获器的调用
    为了替换缺省的截获器链调用顺序,可以设置发布描述符文件的“interceptor-order”。

  3.3 示例

@Stateless(name="Trader")
@Interceptors(ClassInterceptor.class)
public class TraderBean implements Trader {
@Interceptors(MethodInterceptor.class)
public String sell(String stockSymbol) {

}
@AroundInvoke
public Object selfInterceptor(InvocationContext) throws Exception {

}
}

  在无状态会话bean TraderBean中,声明了两个截获器:一个类级截获器,一个方法级截获器,此外,通过使用@AroundInvoke标注,TraderBean的方法selfInterceptor被声明为截获器方法,所以TraderBean就是bean级截获器。

4 EJB3.0规范在依赖注入和截获器方面的不足

  从依赖注入方面来说,EJB3.0目前支持的注入类型是非常有限的,诸如List、Map之类的集合类型都不能被注入。

  另一方面,EJB3.0的截获器可被看作是一种AOP模型,截获器类相当于方面(Aspect),而截获器方法相当于通知(Advice),但这种AOP是非常简单的:

    不支持引入(Introduction);
    不支持切入点(Pointcut)模式
    通过标注告诉容器某个EJB需要使用截获器,从而使得这种AOP模型具有一定的侵入性

5 WebLogic Server 10 EJB3.0容器简介

   5.1 Pitchfork 简介

  Pitchfork是由Interface21与BEA合作开发的一个具有Apache License的开源项目,作为Spring的“增值”项目,开发Pitchfork有两个目的:

    当前应用服务器可使用Pitchfork实现Java EE 5中的依赖注入,标注处理以及EJB3.0中的截获器。
    在Spring容器中支持Java EE 5的标注

  5.2 WebLogic Server 10 EJB3.0容器的架构

  WebLogic Server 10完全支持Java EE 5和EJB3.0,其EJB3.0 容器是基于Pitchfork来实现依赖注入与截获器的,而Pitchfork又利用了Spring的依赖注入和AOP。此时,WebLogic Server 10的用户有两种选择:

    使用EJB3.0标准模型: EJB bean实例由EJB容器创建,然后由Pitchfork实施Java EE 5 的依赖注入和截获器,这是WebLogic Server 10的缺省配置。
    使用Spring扩展模型:EJB bean实例由Spring容器创建并实施Spring的依赖注入,然后由Pitchfork实施Java EE 5的依赖注入,EJB3.0截获器和Spring AOP。

6 Spring扩展模型

  6.1 使用Spring扩展模型的主要开发步骤

    下载某个版本的Spring类库(最好是由BEA指定的版本),至少需要包括以下jar文件:spring.jar, aspectjweaver.jar, commons-logging.jar, log4j-1.2.14.jar,如果需要,还可以增加其它jar文件。
    将这些jar文件加入到WebLogic Server 10的类路径中。
    创建文本文件Weblogic.application.ComponentFacotry以标识当前应用将使用Spring扩展模型,其内容只有一行:    Weblogic.application.SpringComponentFactory。
    创建/META-INF/services子目录,然后放入前面创建的文件Weblogic.application.ComponentFacotry
    建立Spring 配置文件,并放入到/META-INF目录下,如果是EJB应用程序,Spring配置文件的名字应该是spring-ejb-jar.xml,如果是Web应用程序,Spring配置文件的名字则是spring-web.xml.
    为了使EJB bean能利用Spring的依赖注入与AOP,需要同时将其定义在spring-ejb-jar.xml(或spring-web.xml)中,从Spring角度来看,这就是一个普通的Spring bean,只不过它的id或name必须与对应的EJB name相同。
    将上述目录文件、相关的Java类、部署描述符等打包成标准的jar文件、war文件或ear文件。

  需要注意的是,在Spring配置文件中定义的bean,如果它也是一个EJB bean,则该Spring bean的class属性会被忽略以避免潜在的冲突。

  6.2 示例

  示例一:利用Spring的依赖注入。本例将演示两点,(1) 注入一个集合类型,(2) 注入一个Spring POJO对象

  (1) 开发一个bean类

@Stateless(name="AccountManagementBean")
@Remote({examples.AccountManagement.class})
public class AccountManagementBean
{
private List accountList;
private BusinessObject businessObject;
public boolean doBusiness(String account) {
if (accountList.contains(account)) {
businessObject.doBusiness();
return true;
}
return false;
}
public BusinessObject getBusinessObject() {
return businessObject;
}
public void setBusinessObject(BusinessObject businessObject) {
this.businessObject = businessObject;
}

public List getAccountList() {
return accountList;
}
public void setAccountList(List accountList) {
this.accountList = accountList;
}
}
  (2) 一个POJO

public class BusinessObjectImpl implements BusinessObject
{
private String result;

public void doBusiness() {
System.out.println("I am doing business, the result is: " + result);
}

public String getResult() {
return result;
}

public void setResult(String result) {
this.result = result;
}
}
  (3) Spring-ejb-jar.xml


<beans>
<bean name="BusinessObject" class="examples.BusinessObjectImpl">
<property name="result" value="success" />
</bean>
<bean id="AccountManagementBean">
<property name="businessObject" ref="BusinessObject" />
<property name="accountList">
<list>
<value>Safin</value>
<value>Amy</value>
<value>Albert</value>
<value>Yang</value>
</list>
</property>
</bean>
</beans>

  示例二:利用Spring 的AOP。本例演示了混合使用JEE interceptor、基于代理的Spring AOP以及AspectJ的Aspect

  (1) 开发一个bean类

@Stateless(name="AccountManagementBean")
@Remote({examples.AccountManagement.class})
public class AccountManagementBean
{
public AccountManagementBean() {}
@Interceptors({examples.JEEInterceptor.class})
public boolean doBusiness(String account) {
System.out.println("I am doing business " + account);
return true;
}
}

  (2) 开发一个JEE interceptor

public class JEEInterceptor {
@AroundInvoke
private Object intercept(InvocationContext inv) throws Exception{
System.out.println("I am in JEEInterceptor.intercept()");
return inv.proceed();
}
}

  (3) 开发一个Advice

public class SimpleAdvice implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("I am in Spring AOP interceptor");
return invocation.proceed();
}
}

  (4) 开发一个Pointcut

public class SimpleStaticPointcut extends StaticMethodMatcherPointcut {
public boolean matches(Method method, Class cls) {
return "doBusiness".equals(method.getName());
}
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class cls) {
return AccountManagementBean.class.isAssignableFrom(cls);
}
};
}
}

  (5) 开发一个AspectJ Aspect

@Aspect
public class Aspects {
@Around("execution(* examples.AccountManagementBean.doBusiness(..))")
public Object around(ProceedingJoinPoint pjp) {
System.out.println(“I am in AspectJ aspect);
Object retVal = null;
try {
retVal = pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
return retVal;
}
}

  (5) Spring-ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="AccountManagementBean" />
<bean id="myAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice">
<bean class=”examples.SimpleAdvice” />
</property>
<property name="pointcut">
<bean class="examples.SimpleStaticPointcut" />
</property>
</bean>
<bean id="MyAspect" class="examples.Aspects" />
</beans>

  6.3 优点

  提供Spring扩展模型具有如下好处:

    可以在同一个发布单元中混合使用EJB bean和Spring POJO,而且一个EJB bean可以同时是一个Spring POJO,因此被EJB容器和Spring容器同时管理
    有效地克服了EJB3.0 规范在依赖注入和截获器方面的一些缺陷
    为用户提供更灵活的选择:
      如果标准的EJB 依赖注入以及截获器可以满足应用需求,或者可移植性是优先考虑的因素,则选用标准模型
      如果标准的EJB依赖注入以及截获器不能满足应用需求,或者不用考虑可移植性,或者需要集成一些Spring应用,则应选用Spring扩展模型

7 Spring AOP在WebLogic Server 10 Spring扩展模型中的使用限制及说明

  7.1 代理生成方式

  Spring AOP采用的是一种基于代理的框架,目前有两种生成代理的方式:JDK动态代理和CGLIB。在WebLogic Server 10的Spring扩展模型中,目前不支持CGLIB方式,这主要是因为生成的EJB类都是final的

  7.2 代理创建

  在Spring中,代理或者是通过诸如ProxyFactoryBean之类的工厂bean明确创建,或者是通过“自动代理”创建器隐含创建。

  在WebLogic Server 10中,Pitchfork已经隐含提供了类似的“自动代理”机制,所以原有的Spring代理创建方式是无效的,换句话说,用户只需要在Spring配置文件中定义目标bean以及对应的Spring Advisor和AspectJ Aspect, 不需要再定义ProxyFactoryBean和“自动代理”创建器,Pitchfork会自动为我们创建AOP代理

  7.3 截获的顺序问题

  在Spring扩展模型中,可以混合使用JEE截获器、Spring Advisor以及AspectJ Aspect,此时的调用顺序为JEE截获器、Spring Advisor以及AspectJ Aspect。

  7.4 bean的实例化模式

  缺省方式下,Spring bean是Singleton的,即Spring容器总是返回同一个bean实例,在Spring扩展模型中,这意味着同一个Spring Advisor或AspectJ Aspect实例将被应用到不同的EJB bean实例上,如果Advisor或Aspect实例是有状态的,这可能会产生问题,为此我们推荐如下的使用方式:

   SLSB & MDB
    带有状态的Advisor或Aspect
     不推荐用带有状态的Advisor或Aspect,除非用户意识到相关的后果并认为这种后果是可以接收的,此时的实例化模式取决于具体应用
    没有状态的Advisor或Aspect
     采用Singleton实例化模式
   SFSB
    带有状态的Advisor或Aspect
     正常情况下应该采用的实例化模式是Prototype,除非用户意识到采用Singletong的后果并认为这种后果是可以接收的
    没有状态的Advisor或Aspect
     采用Singleton实例化模式

8 结束语

  依赖注入和截获器的引入,使得EJB3.0克服了很多EJB2.1的缺点,但与开源社区中流行的轻量级容器相比,EJB3.0无论是在依赖注入的范围还是在AOP的易用性方面都还存在一定的不足。而最近BEA所推出的WebLogic Server 10不但完全支持EJB3.0,而且对其进行了有效扩展,这使得一方面可以充分利用在开源社区中出于领导地位的Spring在依赖注入和AOP方面的强大能力,另一方面又紧密依托WebLogic Server 10在事务、安全、集群方面领先的技术,从而为EJB3.0用户开发出易维护、可扩展、高效率的企业应用程序打下坚实的基础。

分享到:
评论

相关推荐

    EJB3.0+weblogic操作文档

    在本教程中,我们将关注如何在WebLogic 11g服务器上发布和使用EJB3.0项目。 1. **无状态会话Bean(Stateless Session Bean)**: - 无状态会话Bean是最简单的EJB类型,它不维护任何会话状态,每个请求都独立于其他...

    Ejb3.0 Local Working In Weblogic10.3

    EJB(Enterprise JavaBeans)是Java EE平台中的核心组件,用于构建可复用、安全且事务处理能力强大的服务器...理解并熟练掌握EJB 3.0的本地接口及其在WebLogic中的应用,对于开发高效、稳定的Java EE应用具有重要意义。

    ejb3.0+Weblogic+Jboss安装配置及入门例子

    在WebLogic中部署EJB通常涉及以下步骤: 1. 创建新的WebLogic域并配置服务器。 2. 将EJB项目的JAR文件添加到WebLogic的部署目录。 3. 使用WebLogic管理控制台或命令行工具(如WLST - WebLogic Scripting Tool)进行...

    李腾飞EJB3.0 源码 源代码

    5. **依赖注入(Dependency Injection,DI)**:EJB 3.0支持依赖注入,通过`@EJB`、`@Inject`等注解,可以方便地注入其他服务或者Bean,增强了代码的可维护性和可测试性。 6. **事务管理**:EJB 3.0提供了自动的...

    ejb3.0开发规范PDF

    EJB(Enterprise JavaBeans)3.0是Java企业级应用开发的一个重要标准,它定义了如何在Java EE(Java Platform, Enterprise Edition)环境中构建可复用的、组件化的服务器端应用程序。EJB 3.0的发布极大地简化了EJB的...

    EJB3.0架包

    10. **EJB容器**:EJB3.0运行在Java EE应用服务器内,如WildFly、GlassFish或WebLogic,这些服务器提供了EJB容器来管理Bean的生命周期、事务、安全性和资源。 综上所述,EJB3.0是一个强大的企业级开发框架,它的...

    中文最新EJB3.0实例教程下载

    在《中文最新EJB3.0实例教程》中,你将学习如何创建和部署EJB3.0组件,如何使用JPA进行数据持久化,以及如何利用依赖注入和事务管理构建可扩展和可靠的业务应用。教程中可能包含实际的项目案例,通过实践操作来加深...

    ejb3.0入门图文教程

    在整个学习过程中,你将了解到EJB 3.0的核心概念,如依赖注入、容器管理的事务、安全性和性能优化。这些知识对于理解和构建企业级Java应用程序至关重要。同时,EJB 3.0的可读性强和简洁的编程模型也使其成为开发者...

    ejb3.0开发实例(java工程)

    3. **依赖注入(Dependency Injection)**:EJB 3.0支持JSR 330规范,通过@Autowired、@Inject等注解实现依赖注入,降低了组件间的耦合度,提高了代码的可测试性和可维护性。 4. **会话Bean**:会话Bean是EJB的核心...

    EJB3.0规范中文版

    4. **依赖注入(Dependency Injection)**:EJB 3.0支持Java EE的依赖注入机制,使得组件之间可以通过容器管理的依赖关系进行协作。例如,`@EJB`、`@Inject`和`@Resource`注解可用于注入其他Bean或资源。 5. **事务...

    EJB3.0+JBOSS+MyEclipse初体验(完整代码和过程)

    在JBOSS中部署和运行EJB 3.0应用,开发者可以享受到其提供的全套服务,包括事务管理、安全、资源注入等。JBOSS的热部署功能使得开发过程更为便捷。 **MyEclipse与EJB 3.0** MyEclipse是一款集成开发环境,尤其适合...

    EJB 3.0实例教程.pdf

    EJB 3.0是EJB规范的一个重大革新,它极大地简化了EJB的开发过程,引入了许多面向开发者友好的特性,如注解、依赖注入以及更轻量级的架构。 **1. 注解驱动的开发** 在EJB 3.0之前,开发者需要编写大量的XML配置文件...

    EJB 3.0规范官方文档

    EJB(Enterprise JavaBeans)3.0规范是Java EE(Enterprise Edition)平台中核心的组件模型,用于构建可扩展、安全且易于管理的企业级应用程序。EJB 3.0是EJB规范的一个重要里程碑,因为它引入了许多重大的改进,...

    《EJB 3.0入门经典》 源码

    在"ejb3.0入门经典教程-source"这个压缩包中,包含了书中各个章节的示例代码,覆盖了EJB 3.0的各个方面,例如实体Bean的创建、会话Bean的使用、事务管理、安全性设置以及JPA的持久化操作等。这些源码对于初学者来说...

    ejb3.0规范PDF

    EJB(Enterprise JavaBeans)是Java EE平台中的核心组件,用于构建可扩展、安全和事务处理的服务器端应用程序。EJB 3.0是EJB规范的一个重要版本,它引入了许多改进,使得企业级开发变得更加简洁和高效。下面将详细...

    精通EJB3.0 pdf

    而在EJB3.0中,引入了无接口视图的概念,即Bean可以直接暴露其公共方法作为服务,而无需实现额外的接口。这不仅减少了代码量,还提高了开发效率和程序的可读性。 ### 学习EJB3.0的重要性 对于企业级Java开发者而言...

    Java之精通EJB3.0.pdf

    4. **异步方法调用:**在EJB3.0中,可以通过简单的注解来实现异步方法调用,提高了系统的响应性和可扩展性。 5. **简化生命周期管理:**EJB3.0提供了更为简单直观的方式来管理组件的生命周期,减少了代码量。 #### ...

    EJB3.0API.rar_ejb_ejb3.0a_ejb3.0api

    8. **依赖注入(Dependency Injection, DI)**:EJB 3.0支持JSR 330规范,通过注解实现服务的自动装配,如`@Inject`,使得bean之间的依赖关系更加清晰,降低了代码的耦合度。 9. **异步方法调用**:EJB 3.0允许会话...

Global site tag (gtag.js) - Google Analytics