InfoQ

新闻

John Heintz谈如何向Java注解添加行为

作者 Srini Penchikala译者 张龙 发布于 2008年8月15日 下午1时59分

社区
Java
主题
AOP
标签
AOP,
注释,
元编程,
AspectJ

将常见可重用的行为以定制注解的方式添加到Java应用中是一种非常棒的方式,但如果开发者在决定使用注解的时候能够遵循一些开发标准和最佳实践的话,那就更事半功倍了。比如说在计划使用注释之前,比较一下当前情况下是不是注释真的比内迁代码和接口更为贴切。New Aspects的John Heintz在最近举行的No Fluff Just Stuff(NFJS)俄亥俄州软件中心研讨会(COSS)上作了一个演讲,讨论了向Java注解添加行为的多种设计技术。

讲中,John简要地谈到了字节码和元编程技术,大体介绍了Java应用中的元数据是如何在早期Java版本中使用属性文件、XML到现在逐渐发展到注解上来的过程。他也提到了制定JSR-175规范的目的在于为Java语言提供元数据工具,比如Java 5中就已经添加了注解。

定义注解与定义接口的方式相似(使用@Interface类型来声明注解)。注解不仅可以用在包级别上,也可以用在类成员(属性、方法、构造方法),甚至还可以用在方法的局部参数上。

保持策略(retention policy)是实现注解的重要一环,根据数据在内存中保持时间的长短,有三种类型的保持策略:

  • Runtime(一直保留数据,可以通过反射来访问)
  • Class(数据保留在字节码中,无法在运行时访问)
  • Source(编译器不保留该数据)

一些流行框架如EJB3HibernateSpringSeamStruts 2RIFEJAX-WS的新版本都开始支持注解。John论述了处理注解的三种方式:

生成器:
这种注解处理方式是通过读取源代码来产生新的源代码,或修改现存源代码及其它一些文件(XML、文档等等)来实现。生成器主要依赖于容器或其它编码约定,可以在任何保持策略下工作。

使用生成器的例子有注解处理工具(Annotation Processing Tool,即APT)和处理器、XDoclet、Spoon(针对Java的扩展编译器)、APT-Jelly(一个模板库)等。APT不允许你修改源代码,但对产生辅助文件却有相当大的帮助(像WSDL、文档)。

字节码转换:
注解处理器对带有注解的类文件进行解析,然后对类做一些设当的修改。此外,他们也能生成其他类型的文件(比如XML配置文件)。字节码转换器在离线状态(编译期)、在装载期都能运行,还能在运行时动态运行(使用JVMTI API)。在class或runtime这样的保持策略下,它都能运行。

使用字节码转换器的例子有AspectJ、Spring、Hibernate、CGLibJavassistASMBCEL等。

运行时反射:
这种方式使用反射API以编程的方式在运行阶段检查对象。它主要依赖于容器或其他编码约定,同时也需要runtime保持策略。

使用运行时反射的例子有:Java 5及更新Java版本中的反射、Commons Attributes。 像JUnitTestNG这样的测试框架也使用运行时反射来处理注解。

John采用一个Java示范应用向大家展示了如何结合APT、Javassist、AspectJ及反射(使用了Java动态代理)等多种设计技术来定制注解。他还展示了如何向类、属性和方法中添加行为,也谈到了如何使用Aspects来注解类型和方法。

此外,John还提到了Aspect Processing的好处,如容易实现(需要好工具的支持)、语义细致——可以影响到方法调用,甚至是属性的访问(在这点上,和反射和APT不同),还能够集成多个类库的注解,并支持特定的领域抽象。他建议开发人员说,如果Java代码可以以接口的方式实现,那就用接口,不要去用注解。他还建议大家不要对所有东西都使用注解,因为POJO(Plain Old Java Object)要比HAJO(Heavily Annotated Java Object)好。在演讲中,他列举了其它一些最佳实践准则,比如:

  • 注解要添加在最高层次的抽象上(比如在类和方法这两个层次上,注解要尽量添加在类上面)
  • 在面对规则的时候,尽量使用合适的默认值,而且只对exception添加注解。比外,还要尽量少用参数。
  • 将注解作为“规约优于配置”法则的补充(如Spring)
  • 使用反射来增强现有框架(如测试)
  • 利用Javassist和CGLIB框架来产生新的对象,对于底层来说,可以提高字节码转换效率
  • 使用APT来生成非代码文件

查看英文原文:John Heintz on Adding Behavior to Java Annotations

3 条回复

回复

好像有个错字 发表人 micro dict 发表于 2008年8月19日 下午9时25分
Re: 好像有个错字 发表人 王 寒 发表于 2008年8月20日 下午9时15分
Re: 好像有个错字 发表人 leon xiao 发表于 2008年8月21日 上午12时2分
  1. 返回顶部

    好像有个错字

    2008年8月19日 下午9时25分 发表人 micro dict

    比较一下当前情况下是不是注释真的比内迁代码和接口更为贴切


    什么叫内迁?

  2. 返回顶部

    Re: 好像有个错字

    2008年8月20日 下午9时15分 发表人 王 寒

    内嵌

  3. 返回顶部

    Re: 好像有个错字

    2008年8月21日 上午12时2分 发表人 leon xiao

    厉害

独家内容

剖析短迭代

敏捷教练Dave Nicolette提出:我们应该如何设定迭代长度?是要根据发布周期的时间么?使用短迭代又有哪些好处?

应用JSF、Ajax和Seam开发Portlets(1/3)

本文主要讲述了如何用JBoss Portlet Container 和JBoss Portlet Bridge创建新项目,怎样配置一个JSF应用去使用JBoss Portlet Bridge,以及JBoss Portlet Bridge所具备的功能。

AtomServer:数据分发的发布动力(第二部分)

在这篇文章里,Bryon Jacob和Chris Berry将和我们继续探讨AtomServer,它是基于Apache Abdera的完整Atom存储实现。作者还创建了几个Atompub规范扩展,其中包括自动标记、批处理和Feeds聚合。

架构师(试刊第二期)

InfoQ中文站的电子杂志《架构师》试刊第二期出版了!相比于上期,我们在内容的选择安排和版式上都根据读者的意见重新做了修正。“细节决定成败”,我们希望基于InfoQ中文站的专业内容,《架构师》能逐渐成为大家喜欢的电子刊物!

一种正规的性能调优方法:基于等待的调优

在本文中,Steven Haines探讨了Web应用性能调优问题。该领域过去更像是一门艺术而不是一门科学。他提出了一种称为基于等待调优的方法,使整个调优过程更加可度量,也因此更具科学性。

Java程序员ActionScript 3入门

通常来说,改变技术路线时最艰难的部分是辨别语言语法之间的不同。这篇文章就为Java开发者提供了一份如何转向Flex基础语言ActionScript的指南。

浅谈如何创建Rails应用

本视频主要以财帮子为例,介绍了如何创建一个PV为百万级的Rails应用。其中包括:Rails应用的服务器架构、Rails Cache的优化、负载均衡的处理、Web服务器的调试、分布式解决方案、Open API的设计等等。

Alexandru Popescu谈InfoQ.com网站架构

InfoQ首席架构师Alexandru Popescu在采访中谈论了InfoQ架构、Webwork与DWR、Hibernate与JCR、Hibernate可扩展性、最新的InfoQ视频流系统和InfoQ的未来规划。