`

【转】面向Java EE 6平台的上下文和依赖性注入

    博客分类:
  • Java
阅读更多
【51CTO精选译文】Java EE 6平台的发布带来了几个新的技术亮点。在前几周,我们介绍了Java EE平台的主要目标以及Java EE 6的RESTful Web Services Java API (JAX-RS)特性,本文将介绍面向Java EE平台的上下文和依赖性注入(CDI)。

JSR 299是一种为Java EE组件提供强大服务的技术,这些服务允许Java EE组件,包括EJB会话Bean和JavaServer Faces(JSF)托管的Bean,绑定到生命周期上下文,注入,并以松耦合的方式交互。最重要的也许是,CDI统一和简化了EJB和JSF编程模型,允许企业Bean替换JSF应用程序中JSF托管的Bean。

本质上,CDI是Java EE平台的Web层和企业层之间的一座桥梁,企业层通过如EJB和JPA等技术,已经对事务性资源提供了强有力的支持。例如,使用EJB和JPA(51CTO编辑推荐:EJB应用开发专栏),你可以轻松构建与数据库交互的应用程序,在数据上提交或回滚事务,以及持久化数据。相比之下,Web层重点是展示。Web技术如JSF和JSP提供用户界面,显示它的内容,没有集成处理事务资源的工具。51CTO编辑推荐您阅读《Java EE 6平台指南》专题了解更多。

通过它的服务,CDI使Web层也支持事务,这样在Web应用程序中访问事务资源就更容易了。例如,CDI使得构建一个用JPA提供的持久化访问数据库的Java EE Web应用程序就更容易了。

让我们再看看使用CDI服务的Web应用程序的关键部分,处理用户登录和注销的应用程序同时包括JSF和EJB组件。下面是一个显示登录提示JSF页面中的输入窗体代码:

   1. <f:view>
   2.        <h:form>
   3.            <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
   4.               <h:outputLabel for="username">Username:h:outputLabel>
   5.               <h:inputText id="username" value="#{credentials.username}"/>
   6.               <h:outputLabel for="password">Password:h:outputLabel>
   7.               <h:inputText id="password" value="#{credentials.password}"/>
   8.            h:panelGrid>
   9.            <h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
  10.            <h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
  11.        h:form>
  12.    f:view>
  13. 

你可以从代码中看到,登录提示显示区域包括输入用户名和密码,同时还显示了一个登录按钮和退出按钮。注意统一表达式语言(EL)表达式,如# {credentials.username}和#{login.login},这些表达式引用了名叫credentials 和 login的Beans。

请注意CDI是构建在Java EE 6引入的新概念托管Beans之上的,其目的是统一Java EE 6中所有类型的Beans。一个托管Bean就是一个Java类,被视为由Java EE容器托管的组件,另外,你可以为其指定一个与EJB组件同名的命名空间,一个托管Bean也可以依赖少量的容器提供的服务,主要与生命周期管理资源注入有关,其它Java EE技术,如JSF,EJB和基于托管Bean构建的CDI,一个JSF托管Bean添加到生命周期范围,一个EJB会话Bean添加如支持事务的服务,CDI添加入依赖性注入的服务,在CDI中,一个托管Bean或一个简单的Bean是可以被其它组件,关联的上下文或通过EL表达式注入的Java EE组件。

使用javax.annotation.ManagedBean注解或CDI注解,如范围注解或限定注解,注解它的类来声明一个托管Bean,后面将会介绍范围注解和限定注解。基于注解的编程模型使得一个Bean开始是一个POJO,然后又转换成另一种Java EE组件,如EJB组件成为可能,也许要使用更高级的功能,如事务和安全注解,或由EJB容器提供的实例,例如,你可以向对象添加一个@Stateful 注解将一个POJO转换成一个状态会话,使用CDI的客户端访问Bean不受影响,因为POJO已经转换成EJB了。

这里列举的应用程序中,一个名叫Credentials的Bean有一个绑定到JSF请求的生命周期,Credentials Bean是象下面这样实现的一个JavaBean:

   1. @Model
   2.    public class Credentials { 
   3. 
   4.       private String username; 
   5.       private String password; 
   6. 
   7.       public String getUsername() { return username; } 
   8.       public void setUsername(String username) { this.username = username; } 
   9. 
  10.       public String getPassword() { return password; } 
  11.       public void setPassword(String password) { this.password = password; } 
  12.    } 
  13. 

为了请求一个CDI服务,可以使用CDI注解注解一个Java EE组件,@Model注解是一个CDI注解,它将Credentials Bean作为模型-视图-控制器(MVC)架构中的模型对象,内置于CDI中的注解是一种固定模式的注解,固定模式注解将类标记为满足应用程序内的特定角色。

应用程序还包括一个Login Bean,它的生命周末是和HTTP会话绑定到一起的,Login Bean是作为一个EJB状态会话Bean实现的,代码如下:

   1. @Stateful
   2.    @SessionScoped
   3.    @Model
   4.    public class Login { 
   5. 
   6.       @Inject Credentials credentials; 
   7.       @Inject EntityManager userDatabase; 
   8. 
   9.       private User user; 
  10. 
  11.       @TransactionAttribute(REQUIRES_NEW) 
  12.       @RolesAllowed("guest") 
  13.       public void login() { 
  14.          ... 
  15.       } 
  16. 
  17.       public void logout() { 
  18.          user = null; 
  19.       } 
  20. 
  21.       public boolean isLoggedIn() { 
  22.          return user!=null; 
  23.       } 
  24. 
  25.       @RolesAllowed("user") 
  26.       @Produces @LoggedIn User getCurrentUser() { 
  27.          ... 
  28.       } 
  29.    } 
  30. 

@Stateful注解是一个EJB注解,它指定这个Bean是一个EJB状态会话Bean,@TransactionAttribute 和@RolesAllowed也是EJB注解,它们声明EJB事务划分和注解方法的安全属性。

@SessionScoped注解是一个CDI注解,它给Bean指定一个范围,所有的Bean都有一个范围确定其实例的生命周期和这个实例对其它 Bean的实例是否可见,这是一个很重要的特性,因为EJB组件没有定义良好的范围,尤其是EJB组件不能感知请求,会话和应用程序Web层组件,如 JSF托管Bean的上下文,也不能访问与这些上下文关联的状态。此外,状态EJB组件的生命周期不能作用到Web层上下文。

相比之下,CDI中的作用域对象有一个定义良好的由Java EE容器托管的生命周期上下文,作用域对象可能是按需自动创建的,当上下文创建完毕后又自动销毁的,值得注意的是,作用域状态在相同上下文中执行的客户端之间是自动共享的,这意味着客户端,如其它在相同上下文中执行的Beans,会被当作相同的对象实例看待,但在不同上下文中的客户端看到的是不同的实例。 @SessionScoped注解指定Login Bean的作用域类型是会话作用域。对象通常不会与作用域关联,一般依赖于它们的所有者,这些依赖对象的生命周期是和它们的所有者联系在一起的,一个依赖对象当它的所有者被销毁后它也自动销毁。

Beans通常通过依赖性注入引用其它Beans,依赖性注入机制是一个完全的类型安全,CDI使用JSR 330-Java依赖性注入中指定的注解进行依赖性注入,@Inject就是其中一个注解,它指出Java类或接口上哪个依赖点可以被注入,容器然后提供需要的资源,在这个例子中,Login Bean指定了两个注入点,第一个使用@Inject注解在Credentials Bean上注入一个依赖,容器将会把Credentials Bean注入到这个上下文中创建的所有Login实例上,第二个@Inject注解在JPA EntityManager上注入一个依赖,容器将会注入EntityManager管理持久化上下文。

@Produces注解将getCurrentUser()方法认为是一个生产者方法,每当系统中的另一个Bean需要指定类型的注入对象时就会调用生产者方法,在这个例子中,注入对象是当前登录的用户,它是通过限定注解@LoggedIn注入的,为了使用限定注解,你首先需要将它的类型定义为一个限定器,再使用@Qualifier注解,如:

   1. @Target( { TYPE, METHOD, PARAMETER, FIELD }) 
   2.    @Retention(RUNTIME) 
   3.    @Documented
   4.    @Qualifier
   5.       public @interface LoggedIn {...} 
   6. 

    * Java EE 6新特性尝鲜:EJB 3.1重要变化..
    * Java EE 6,貌似民主下的虚伪公平
    * Sun的技术爆发 Java EE 6等三重量级产品..
    * Java EE 6总览:平台的主要目标
    * Java EE 6引入的三大新技术之JAX-RS

让我们再回到前面讨论的登录提示,当用户响应提示并点击了提交按钮后,CDI技术开始付诸行动,Java EE容器(51CTO编辑推荐:Java EE容器调查:Tomcat大受欢迎 WebLogic成时间杀手)自动实例化Credentials Bean和Login bean的一个上下文实例,一个绑定上下文的Bean的实例叫做上下文实例,JSF指定输入给Credentials Bean上下文实例的用户名和密码,接下来JSF调用Login上下文实例中的login()方法。这个实例对于相同HTTP会话中的其它请求继续存在并可继续使用,并为其它请求它的Bean提供表示当前用户的User对象。

这个例子只说明了这个技术的一部分功能,其它功能如可以让Bean产生或消费事件,定义截取者跨所有Bean类型绑定额外的功能,或者定义装饰者在指定Bean类型上应用额外的功能。
分享到:
评论

相关推荐

    java ee 6 with glassfish 3

    CDI是Java EE 6中的核心组件管理框架,提供依赖注入(DI)和上下文管理,允许开发者声明性地管理对象的生命周期和依赖关系,极大地提高了代码的可测试性和可维护性。 3. **EJB 3.1**: EJB(Enterprise JavaBeans...

    Java EE Web编程(Eclipse 平台)

    11. **CDI(Contexts and Dependency Injection)**:CDI为Java EE提供依赖注入和上下文管理,简化了组件的装配和管理。 12. **WS(Web Services)**:讲解如何创建和消费SOAP或RESTful Web服务,包括WSDL、JAX-WS...

    The Java EE 6 Tutorial: Basic Concepts, 4th Edition

    《Java EE 6 Tutorial: Basic Concepts, Fourth Edition》是一本面向新手及中级Java开发者的指南书籍,旨在帮助他们深入理解Java平台企业版6(Java EE 6)的各项特性与技术。本书由Oracle公司Java EE 6文档团队成员...

    java ee api

    9. **CDI(Contexts and Dependency Injection)**:提供依赖注入和上下文管理,简化了对象之间的依赖关系。 10. **JAX-RS(Java API for RESTful Web Services)**:用于构建RESTful服务,基于HTTP协议,使得服务...

    java-ee-api原版

    4. **CDI (Contexts and Dependency Injection)**:CDI为Java EE应用提供依赖注入和上下文管理,使得组件之间的依赖关系更加清晰,提高了代码的可测试性和可维护性。 5. **EJB (Enterprise JavaBeans)**:EJB是Java...

    Beginning JAVA EE 7经典

    2. CDI:是Java EE中用于依赖注入和上下文管理的规范,它负责管理Java EE应用程序中的对象生命周期和依赖关系。 3. EJB:作为Java EE规范的核心组件,EJB允许开发者创建可重用的商业逻辑组件,能够简化事务管理、...

    java ee教程(电子教案)

    7. **CDI(Contexts and Dependency Injection)**:CDI为Java EE应用提供依赖注入和上下文管理,简化组件之间的依赖关系和生命周期管理。 8. **WS(Web Services)**:Java EE支持SOAP和RESTful两种类型的Web服务...

    精通Java EE:精通Java EE 整合应用案例\源代码第三章

    6. **CDI(Contexts and Dependency Injection)**:CDI是Java EE中的依赖注入和上下文管理规范,使得对象的创建和管理更加自动化,提高了代码的可测试性和可维护性。 在源代码第三章中,你可能通过实际的案例研究...

    Professional Java EE Design Patterns

    - Dependency Injection(依赖注入)和CDI(上下文和依赖注入)(第5章)是一种设计模式,用于实现控制反转(IoC),减少组件之间的耦合度。 - Factory(工厂)模式(第6章)通过使用一个共同的接口来创建对象,但让...

    The Java EE 6 Tutorial.Volume I.pdf

    - Contexts and Dependency Injection (CDI):用于实现依赖注入和上下文管理的API。 #### 四、技术特点 1. **模块化架构**:Java EE 6引入了一种新的模块化架构,使得开发者能够更加灵活地选择所需的技术组件,...

    Pro CDI 2 in Java EE 8

    5. **上下文与作用域**:CDI提供了多种上下文,如@RequestScoped、@SessionScoped、@ApplicationScoped等,它们决定了bean的生命周期和可见性。开发者可以根据需求选择合适的作用域,以满足不同场景下的需求。 6. *...

    java_ee_api

    10. **CDI(Contexts and Dependency Injection)**:CDI提供依赖注入和上下文管理,简化了组件的装配和生命周期管理,降低了代码间的耦合度。 以上只是Java EE API中的一部分关键组件和服务。在实际开发中,开发者...

    Java EE实用教程+源代码

    6. **CDI(Contexts and Dependency Injection)**:CDI提供依赖注入和上下文管理,使得组件间的依赖关系更加清晰,降低了代码的耦合度。 7. **JMS(Java Message Service)**:JMS允许应用程序通过消息传递进行...

    JAVA EE API

    10. **CDI(Contexts and Dependency Injection)**:CDI是JAVA EE中用于依赖注入和上下文管理的标准,它简化了组件之间的依赖关系管理,提供了声明式的服务发现和事件模型。 这些API和框架共同构建了JAVA EE的强大...

    java ee软件工程师技术要点列表

    - CDI为Java EE应用提供依赖注入和上下文管理,简化组件的装配和生命周期管理。 9. **JAX-RS(Java API for RESTful Web Services)**: - JAX-RS是Java EE中用于构建RESTful Web服务的API,允许开发者用注解来...

    Beginning Java EE 7 javaEE7入门

    - 上下文和依赖注入(Context and Dependency Injection, CDI):CDI是Java EE的核心组件之一,用于管理对象之间的依赖关系,并提供了一个上下文环境,使得对象可以与环境相关联。这样,应用可以更加灵活地管理对象,...

Global site tag (gtag.js) - Google Analytics