Java EE6 Weld(1): 上下文、依赖注入和限定词

标签: java ee6 weld | 发表时间:2012-02-23 23:26 | 作者:Rogue
出处:http://www.blogjava.net/

 一、Weld简介

    Java EE 6.0 的核心:JSR-299规范,提供了如下功能:

        1. 类型安全的依赖注入
        2. 注入对象的上下文生存周期管理
        3. 事件提醒模型
        4. 绑定拦截器通过用户自定义的注解(Annotation)
        5. 类型安全的装饰器
        6. 为整合第三方框架提供了完整的 SPI 支持
        7. 与 JSF,Servlet / JSP 进行了整合
        8. 对 JSF 提供长会话(Conversation)上下文支持

    Weld 是一个实现了 JSR-299 的框架。主要由JBoss完成其实现,项目主页: http://www.seamframework.org/Weld 。最新发布了  Weld 2.0.0.Alpha1 版本。

    Weld 工程的搭建是非常简单的, 这里介绍一下 Weld+JSF 在 Tomcat 7.x 中的工程搭建的方法:
    1)通过Eclipse 直接建立一个 Dynamic Web Project , Runtime 选择 tomcat7 , Servlet 版本选择3.0 。
    2)添加所需jar文件:由于 tomcat 是非 servlet 容器,所以要加入  weld-servlet.jar 。   还有JSF 的  jsf-api.jar  , jsf-imp.jar  和 jstl-1.2.jar 
    3)在web.xml 添加监听器来启动weld
    <listener>

      <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
   </listener>
    4)在META-INF下,添加context.xml 为tomcat容器JNDI绑定 BeanManager。 
<Context> 
   <Manager pathname=""/> <!-- disables storage of sessions across restarts -->
   <Resource name="BeanManager"
      auth="Container"
      type="javax.enterprise.inject.spi.BeanManager"
      factory="org.jboss.weld.resources.ManagerObjectFactory"/>
   <!-- Uncomment to enable injection into Servlet -->
   <!-- <Listener className="org.jboss.weld.environment.tomcat.WeldLifecycleListener"/> -->
</Context>
    5)在web.xml中,声明注册这个绑定
 <resource-env-ref>
      <description>Object factory for the CDI Bean Manager</description>
      <resource-env-ref-name>BeanManager</resource-env-ref-name>
      <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
   </resource-env-ref>
    6)在WEB-INF下面,放一个空的bean.xml

    在非jee6 或者 非servlet容器下,都需要这样配置的。在Jboss as7中就要简单的多,只需要加入 cdi-api.jar 跟一个 bean.xml  其他的地方就是jsf的一些配置。

    

二、上下文(Context)

    
    Weld 中有5个上下文范围的容器:Request、Session、Application、Dependent 和 Conversation。前面3个就不再介绍了,他们的注解分别为@RequestScoped @SessionScoped @ApplicationScoped 。JSR299中参照了Seam,加入了一个新的会话范围 Conversation
    @Dependent  默认范围,所有没有定义的上下文范围的Class或者Interface 具有这个默认的注解。用EL表达式每次应用一个Dependent范围的bean容器都会重新实例化一个。所以不要用EL应用Dependent范围的bean。每次注入这个范围的bean的时候,容器都会new一个新的实例给注入点。
    @Conversation 可以叫它对话范围,它的范围比Request大,一个Conversation里面可以包含多个Request,比Session范围小。 需要注意的一点,Conversation范围和Session范围的bean会被持久化到你的磁盘上,从而节省你的内存,所以在使用这两个范围的bean的时候需要实现序列化接口(Serializable)。
    在实际应用中,Conversation一般用于使用多个页面来做一件事情,相关的对象不会丢失。但是,Conversation范围并不是它的对象放在Session中,只是在HttpSession这个对象中存放了一个id。
    Conversation 可以分为短对话和长对话两种情况。对于一般的Conversation,它的持续时间是跟Request一样的,并没有太大的区别。下面的方式就可以把一个短对话变成长对话。

1 @Inject
2 Conversation conversation;
3 public void start(){
4     conversation.start();
5     conversation.setTimeout(30000);//5分钟,默认10分钟
6 }
    

三、依赖注入 @Inject

    JSR299 借鉴了现在很流行的依赖注入,自己通过注解也实现了依赖注入,无需像Spring那么多的配置文件。

    weld 的三个注入点:
        1. 构造方法参数:如果在一个bean的构造函数上加上@Inject注解,那么它的参数都是通过依赖注入传入的。也可以把@Inject放在形参的前面。
        2. 初始化方法参数:如果一个方法上有@Inject注解,它不是构造函数的话,上面这中情况,那么这个方法就是 初始化方法  。初始化方法总是会在构造函数之后执行,注入他的参数。
        3. 类属性: 这也是最常用的一种方法,类似与seam2中 @in 。

    下面分别给出这3中情况的例子
@Inject
public HelloAction(CurrentUser user){
}
@Inject
public void sayHello(CurrentUser user){
   System.out.println("Hello, "+user.getName());
}
@Inject
Logger logger;

四、限定词 @Qualifier

    
     我们一般在注入service层的bean的时候,一般会直接注入一个接口,而不是它的实现类。限定词的作用主要用于区分一个接口的不同实现。
    weld 中有两个默认的限定词 @Default 和 @Any:  
        @Default  : 默认限定词,如果一个注入点没指定特定的限定词,那么它就默认使用@Default这个限定词。
        @Any: 如果你一个接口有多个实现类,不同的实现类你使用了不同的限定词来区分,那么 @Any 就可以修饰所有的实现。
   一般情况,需要我们自己定义个注解:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE,Element.METHOD,ElementType.FIEID,ElementType.PARAMENTER)
public @interface Morning{}
    @Qualifier 说明这个新定义的注解是一个限定词。
    @Retention 表明这个注解什么时候作用,一般都是写 RUNTIME
    @Target 表明这个注解可以在什么地方使用,上面的定义分别是 类名上,方法上,属性,参数
    
@Inject @Morning HelloAction helloAction;

    如果一个接口有很多个实现类的话,我们也不需要为每个实现类定义一个注解。我们可以给一个注解加个参数,通过这个参数来指定注入哪个实现类。 
    只需要在个实现类之前加上这个限定词,那么在注入这个接口的时候,就会自动注入这个实现类了。   
@Morning
public class MorningHelloAction Implements HelloAction{
    ...
}
    一个bean如果实现了多个接口,那么只要添加多个限定词就可以了。
    使用了限定词,这样在使用一个接口的时候,我现在不需要关心这个接口实现类的类名,只要你的实现类加了这个限定词,在注入的时候就会自动找到这个类注入进来。这样可以大大的降低了耦合性。


 



Rogue 2012-02-23 23:26 发表评论

相关 [java ee6 weld] 推荐:

Java EE6 Weld(1): 上下文、依赖注入和限定词

- - BlogJava-首页技术区
    Java EE 6.0 的核心:JSR-299规范,提供了如下功能:. 注入对象的上下文生存周期管理. 绑定拦截器通过用户自定义的注解(Annotation). 为整合第三方框架提供了完整的 SPI 支持. 与 JSF,Servlet / JSP 进行了整合. 对 JSF 提供长会话(Conversation)上下文支持.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees [email protected] 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.

java 验证码

- - ITeye博客
// 创建字体,字体的大小应该根据图片的高度来定. // 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到. // randomCode用于保存随机产生的验证码,以便用户登录后进行验证. // 随机产生codeCount数字的验证码. // 得到随机产生的验证码数字. // 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同.

Java异常

- - CSDN博客推荐文章
“好的程序设计语言能够帮助程序员写出好程序,但是无论哪种语言都避免不了程序员写出坏的程序.                                                                                                                          ----《Java编程思想》.

java面试题

- - Java - 编程语言 - ITeye博客
 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面. 抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节. 抽象包括两个方面,一是过程抽象,二是数据抽象.  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法. 对象的一个新类可以从现有的类中派生,这个过程称为类继承.

Java使用memcached

- - 互联网 - ITeye博客
首先到 http://danga.com/memcached下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可. 然后是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:c:>;memcached.exe -d install
c:>memcached.exe -l 127.0.0.1 -m 32 -d start.

Java线程池

- - 企业架构 - ITeye博客
线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的. 在jdk1.5之后这一情况有了很大的改观. Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用. 为我们在开发中处理线程的问题提供了非常大的帮助.