依赖注入又称控制反转(IOC)是当前最新的开发潮流。诸 如Spring 等IOC容器变得流行,就是因为它简化了企业java的復杂性,这些復杂性大部份是来自於JNDI。在这篇文章中,我会讨论如何在即将发布的Java EE 5.0中使用依赖注入为资源和服务进行声明。我将使用EJB3.0,Web Servic的元数据和依赖注入移植J2EE1.4蓝图程序java高级编译器。在这篇文章中我将使用这个应用程序去说明这些概念。
版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:EsunYang(作者的blog:http://blog.matrix.org.cn/page/EsunYang)
原文:http://www.matrix.org.cn/resource/article/44/44321_Dependency+Injection.html
关键字:Dependency;Injection
什么是依赖注入?
大多数企业级java应用程序都使用了诸如DataSources,EJBs或WebService的外在的资源和服务,在J2EE 1.4中,用户必须在部署描述符中明确声明所依赖的资源或者使用JNDI的lookup方法去获得资源的引用。
例如,如果你想在J2EE 1.4 中使用诸如DataSource 或EJB这样的服务,你必须在部署描述符作出类似下面的定义:
ejb/HelloWorld
oracle.ejb30.HelloWorld
然后,在可以使用下列资源之前,你还必须像下面一样使用JNDI去查找这个对象: Context ic = new InitialContext();
HelloWorld helloWorld = (
HelloWorld)ic.lookup("java:comp/env/ejb/HelloWorld");
这些方法不仅仅使java新手感到难以理解,而且容易误导。而这些都归功於J2EE的復杂性。
依赖注入与JNDI相反,它(依赖注入)让你声明依赖,当需要请求资源时,由java EE容器处理资源或服务的復杂实例化和初始化。基於使用註释或部署描述符的资源声明,在必要时,Java EE 5.0容器会插入一个资源实例。图1对JNDI和依赖注入作了比较:
图1. JNDI和依赖注入的比较
在何处使用依赖注入?
依 赖注入仅可以由受管对象使用,受管对象是指由Java EE容器管理的对象,比如EJB或Servlet,而不是那些诸如助手类(helper class)的一切类。例如,如果我们有一个EJB,我们可以在EJB3.0使用依赖註入,而不是在它所依赖的助手类上使用依赖注入。下表列出了在web 和EJB模块中支持依赖注入的类型:
一些Java EE容器,如Oracle Application Server 10g 10.1.3 和 JBoss Application Server 4.0,为EJB3.0提供较早的支持,因此在EJB容器中他们是支持依赖注入的。
正 如我上面的描述一样,你既可以使用元数据註解或部署描术符去声明对资源的依赖。在最近提交的作为最后定稿的JSR250中,为java平臺的通用元数据註 解定义了两个资源依赖注解类(javax.annotation.Resource 和 javax.annotation.Resources),在JSR200中的EJB3.0中,为EJBs的依赖註解定义了javax.ejb.EJB, 而在Java API for XML web service 2.0中为Web Servcie引用的依赖註解定义了javax.xml.ws.WebServiceRef。
Resource 注解可以用於诸如EJB或 Servlet 等受管类,或者它们(受管类)中的方法和字段。你可以用Resource註解去定对任何类别资源的依赖,如DataSource,JMS,Mail, URL,或environment enries(环境条目)。
下面是一javax.annotation.Resource接口的註解声明: public @interface Resource {
public enum AuthenticationType {CONTAINER,APPLICATION
}
String name() default '';
Class type() default Object.class;
AuthenticationType authenticationType()
default AuthenticationType.CONTAINER;
boolean shareable() default true;
String mappedName default '';
description() default '';
}
下表描述了可以在javax.annotation.Resource中指定的参数:
註入类型
Java EE 5.0支持两种类型的註入:field和Setter。Field註入(字段註入)允许你向一字段註入资源,而setter註入(设定註入)允许你通过调用setter方法註入资源。
要使用field註入,只需定义一字段,然註解它所引用的资源。如果你没有定义所引用的资源名称和类型,容器将从字段的名称和类型中继承信息。例如,你可以像下面一样註解DataSource(数据资源):
@Resource
private javax.sql.DataSource AdventureDB;
在上例中,应该配置一个带有AdventureDB JNDI名称的DatatSource﹔如果没有配置的话,将会拋出一个异常。在客户可访问一个受管对象之前,必须先完成对依赖的註入。
相 反,setter 註入(或property 註入)让你按JavaBean规范定义一个set…()方法,并注解它为一个资源引用。应用程序不必去调用这个setter方法,容器会在调业务方法之前 去调用这个用於註入资源的setter方法。例如,如果你有一个名为adventureDB字段,就必须有一名为setAdventureDB的 setter方法。如查你没有定义setter所註入名称和类型,”註入”将从setter方法的名称我参数类型中继承信息。例如,下面有一个对资源进行 引用的setter方法:
@Resource
private void setAdventureDB(javax.sql.DataSource ds)
{
adventureDB = ds;
}
private DataSource adventureDB;
让我们来看一些在 Java EE应用程序中使用Resource 註解进行依赖註入的典型用法。
使用Resource 註解进行依赖註入
使用数据源
在java应用程序中数据源是经常被使用的。你可以使用依赖註入而不是使用JNDI去获得一个数据源。例如,在你的环境中有一个名为jdbc/AdventureDB的数据源,你可以像下面那样去获得对这个数据源的引用:
@Resource(name="jdbc/AdventureDB")
private javax.jdbc.DataSource myDB;
Connection con;
con = myDb.getConnection();
使用JMS资源
Java 消息服务(JMS)使得以消息为向导的中间件(MOM)非常容易被使用,并且在java EE应用程序中这两项技朮被大量地使用。你可以使用资源注解去插入一个如Queue(队列)或Topic(主题)的JMS目标,或如连接工厂的工厂资源。 例如,如果你想使用一个JMS资源,你首先在服务器的配置上创建它,然后像下面那样使用一个@Resource的注解去声明一个依赖:
@Resource(name="jms/WorkFlowManagerQueue")
private Queue wfmQueue;
使用环境条目
环境条目可以让你指定一个因时间或环境不同而变化的业务参数。例如,假设你想在你的应用程序中设定一个用户每月可以交易的最大数量,如果你在应用程序中进行硬编码是没意义的,因为你想在以后可以改变它的数值,或者你想用不同的数值去测试你的產品系统。
比如你想设定maxTradesAllowedPerUser的值为50,你可以像下面那样声明:
@Resource int maxTradesAllowedPerUser = 50