Java 那些事儿 - JavaOne 2011、CDI 和 Google Dart 语言

阅读数:5322 2011 年 11 月 10 日

话题:JavaOracleGoogle语言 & 开发

对于 Java 社区来说,9 月和 10 月间最重要的事件是一年一度的 JavaOne 大会的召开。JavaOne 2011的主题是“推动 Java 向前发展(Moving Java Forward)”。从这个主题可以看出,Oracle 正试图以领导者的身份带领 Java 社区来共同推动 Java 的发展。Java SE 7 的发布,是这个过程中的一个重要里程碑。相对于上一次 JavaOne 会议来说,JavaOne 2011 在社区中的评价比较不错,被认为是一次成功的会议。Oracle 也更加重视社区在推动 Java 发展中的作用。遗憾的是,由于 Google 和 Oracle 之间的专利诉讼,来自 Google 的开发者再一次缺席了 JavaOne 大会。

在 JavaOne 2011 上,Oracle 发布了一些新的技术和项目,也公布了一些重要项目的发展规划。

Java SE 8

根据社区的反馈,Java SE 8 的发布时间从 2012 年底推迟到了 2013 年夏,距离 Java SE 7 的发布差不多正好 2 年的时间。在 Java SE 8 中会包含的内容包括:

  • Jigsaw 项目:为 Java 平台和 Java 应用提供模块化系统的支持。
  • Lambda 项目:为 Java 语言增加闭包的支持。为 Java 集合 API 提供批量并行操作 API,如 filter/map/reduce。
  • JRockit 虚拟机中的部分特性整合到HotSpot 虚拟机中,提供一个统一的虚拟机实现。
  • 集成JavaFX 3.0。在 JavaOne 2011 上 JavaFX 2.0 正式发布,并会在 JDK 7u2 中集成 JavaFX 2.0 的安装。Java SE 8 中则会直接集成 JavaFX 3.0。
  • 虚拟机上可以直接使用的新的 JavaScript 引擎,以及更好的 JavaScript 和 Java 互操作性。新的 JavaScript 引擎称为Nashorn,是一个基于JSR 292的实现。
  • 在移动设备上,增加对多点触摸、摄像头、地理位置信息、罗盘和重力加速器的支持
  • 对 Java 安全、日期 / 时间、网络、国际化和可访问性 API 的更新。

Java EE 7

Java EE 7 的目标是把 Java EE 技术与目前炙手可热的云计算相结合,把 Java EE 平台本身变成一个服务(Platform as a Service,PaaS),同时提供弹性计算(Elastic computing)和多租户(Multi-tenancy)的支持。相对于目前已有的云计算技术,Java EE 7 的最大优势在于标准化和开放性。Java EE 7 的内容包括:

  • 提供平台即服务的支持,包括服务定义和服务提供,以及在 API 中支持多租户。
  • 增强 Web Profile 的能力,增加对 JAX RS 2.0 的支持。
  • 进一步简化开发,包括新的 JMS 2.0,更多的依赖注入的使用,以及更多的服务元数据和优化配置方式等。

Java ME 7

在 Java ME 方面,发展的重点是与 Java SE 保持同步。当 Java SE 中有新的更新时,尽快的同步到 Java ME 中。这其中包括发布版本的同步、Java ME API 可以运行在 Java SE 环境中、以及一致的工具接口等。另外的一个目标是让 Java 平台支持所有不同的平台,不管是什么样的 CPU 和内存限制环境。最后一个方向是与内容和服务进行深度集成,包括访问运营商提供的服务。

CDI

对于依赖注入的概念,相信很多开发人员都不陌生。一个组件在运行过程中会依赖其他组件提供的功能。传统的做法是由组件本身负责查找所需的依赖对象。这种方式会造成组件之间的紧耦合,不利于组件的维护和更新。依赖注入的做法则是由组件以声明式的方式表明其依赖关系,由框架在运行时把所需的组件的 Java 对象注入到当前组件中。相对于 Java SE 来说,依赖注入的概念对于 Java EE 更加适用。Java EE 中的很多资源和服务都是由容器来负责管理的。对于单个应用来说,查找由容器负责管理的组件并不是一件容易的事情。更好的做法是由应用来声明所需的资源和服务,由容器负责注入到应用中。通过这种方式,容器也可以更好的对资源和服务进行管理。以数据库连接为例,传统的做法需要由应用本身加载相关驱动并创建数据库连接,以及在适当的时候进行释放。而使用容器管理并注入依赖的做法,则减轻了应用开发人员的工作量。

Java EE 5 中添加了对依赖注入的有限支持。通过注解可以往容器管理的对象中注入资源的对应对象。Java EE 6 中把依赖注入的概念更进一步,即引入了JSR 299 (Contexts and Dependency Injection for the Java EE platform) 规范,简称 CDI。CDI 规范吸收了来自Spring IoC 容器JBoss SeamGoogle Guice的最佳实践,并与 Java EE 开发的实际需要相结合。正如 CDI 的字面含义一样,CDI 中的两个核心功能是上下文信息(context)和依赖注入。这两个功能的结合点是 Java 中基本的组件模型 bean。在 CDI 中,bean 定义了应用的状态和逻辑,并由容器来进行管理。每个被管理的 bean 都有定义好的绑定到特定上下文的作用域和生命周期。当需要注入或访问 bean 时,容器会从作用域对应的上下文中获取。当作用域失效时,对应上下文中所有的对象都会被删除。CDI 中的每个 bean 都可以作为依赖注入时的目标。

CDI 中预定义了一些常用的作用域。默认的作用域是 Dependent,表示只对被注入的对象生效。作用域 ApplicationScoped 表示应用的全局作用域,用来创建全局唯一的对象。RequestScoped 和 SessionScoped 则与 HTTP 相关,分别表示 HTTP 请求和 HTTP 会话。ConversationScoped 是由应用自定义生命周期长短的作用域,可以用来实现跨多页面的工作流。如下面代码中的 OrderProcessor 类只存活在 HTTP 请求中,并且依赖 OrderDao 接口的实现。容器会在运行时查找到 OrderDao 接口的实现对象,并注入到 OrderProcessor 类的对象中。

@Named
@RequestScoped
public class OrderProcessor {
    @Inject
    private OrderDao orderDao;
}

通常的依赖注入方式是在代码中只依赖接口,由容器在运行时选择合适的实现类的对象来进行注入。如果接口只有一个实现类,则不需要额外的声明。如果接口有不同的实现,则需要使用限定符(qualifier)来声明具体使用的实现,否则容器无法做出正确的选择。CDI 的一个特点是限定符不是普通的字符串,而是类型安全的注解。

通过 Qualifier 元注解可以创建新的限定符注解。如下面的代码创建了一个新的限定符注解 InMemory。

@Qualifier
@Retention(RUNTIME)
@Target({TYPE})
public @interface InMemory {}

该注解可以添加在 OrderDao 接口的实现上。

@InMemory
    public class InMemoryOrderDao implements OrderDao {
}

如果在测试时,希望使用简单的基于内存的存储实现,可以使用 InMemory 注解来声明。这样容器在注入时会使用 InMemoryOrderDao 类的对象。

@Named
@RequestScoped
public class OrderProcessor {
    @Inject @InMemory
    private OrderDao orderDao;
}

使用类型安全的注解类型可以避免使用字符串时会出现的问题。在使用字符串来区分时,可能由于字符串内容的细微错误而造成难以发现的问题。

Google Dart 语言

Google 的开发人员似乎热衷于开发新的编程语言,而且每一次新的语言都很造成比较大的影响。前不久,Google 的开发人员发布了新的编程语言Dart。Dart 语言的目标是创建结构化的 Web 应用。在使用方式上类似 Node.js 和 GWT,即在服务器端和客户端采用相同的编程语言。在 Node.js 中,都是使用的 JavaScript;在 GWT 中则是以 Java 为主;而 Dart 则更像是升级版的 GWT,只是用了一种设计更好的语言来替代 Java。在服务器端,Dart 运行在虚拟机(DartVM)之上;而在浏览器端,则转换成 JavaScript 来执行。

在语法上,Dart 像是 Scala 和 JavaScript 的一个结合体。Dart 中有类和接口的概念,同时类型声明是可选的。在 Dart 中,变量的类型声明是可选的。这么设计的出发点是让开发人员可以根据开发的不同阶段以及应用的类型来选择合适的类型声明策略。在初期的原型开发阶段或是开发小型应用时,使用动态类型是一个不错的选择;而对于复杂的模块化的大型应用来说,采用静态类型则是一个更好的做法。Dart 并不对类型声明的选择做出限制。

下面的 Dart 代码示例展示了可选类型和类继承的基本用法。

class Animal {
    var legs;
    Animal(this.legs); // 简化的构造方法 
    tellMyLegs() { print(this.legs); }
}
class Dog extends Animal {
    Dog() : super(4); 
}
main() {
    var dog = new Dog();
    dog.tellMyLegs(); // 输出 4

}

值得一提的是 Dart 的并发编程模型。Dart 程序在运行时总是单线程的,这点类似 JavaScript。并发性是通过类似Actor的隔离体(isolate)来完成的。每个隔离体是一个并发运行的单元,有自己的内存和执行逻辑。隔离体之间通过消息传递来进行通讯。Dart 中的隔离体与 HTML5 中的Web Worker非常相似。

Dart 的目标并不是替代 JavaScript 或 Java,而是面向移动平台。在 Dart 中,除了核心库之外,还有一个 DOM API 的库,可以对 DOM 进行操作。

Dart 语言由于刚发布不久,很多东西还处于比较初级的阶段。不过相关的资源都是开放源代码的。感兴趣的人可以关注下面的链接:Dart 语言官方网站、Google Code 上的Dart 源代码DartForce网站。最简单的做法是下载LinuxWindows平台(不支持 Windows XP)上的 Dart 虚拟机,并写一些 Dart 代码来进行试验。


感谢张凯峰对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家加入到InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。