`

全文转载 注解开发

 
阅读更多
转于http://www.iteye.com/topic/1123823

有必要对JDK 5.0新增的注解(Annotation)技术进行简单的学习,因为Spring 支持@AspectJ,而@AspectJ本身就是基于JDK 5.0的注解技术。所以学习JDK 5.0的注解知识有助于我们更好地理解和掌握Spring的AOP技术。

了解注解

对于Java开发人员来说,在编写代码时,除了源程序以外,我们还会使用Javadoc标签对类、方法或成员变量进行注释,以便使用Javadoc工具生成和源代码配套的Javadoc文档。这些@param、@return等Javadoc标签就是注解标签,它们为第三方工具提供了描述程序代码的注释信息。使用过Xdoclet的朋友,对此将更有感触,像Struts、Hibernate都提供了Xdoclet标签,使用它们可以快速地生成对应程序代码的配置文件。

JDK5.0注解可以看成是Javadoc标签和Xdoclet标签的延伸和发展。在JDK5.0中,我们可以自定义这些标签,并通过Java语言的反射机制中获取类中标注的注解,完成特定的功能。

注解是代码的附属信息,它遵循一个基本原则:注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。Java语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过Java反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑,而这正是Spring AOP对@AspectJ提供支持所采取的方法。

引用
很多东西的设计都必须遵循最基本的原则,为了防止机器人伤害人类,科幻作家阿西莫夫于1940年提出了“机器人三原则”:第一,机器人不能伤害人类;第二,机器人应遵守人类的命令,与第一条违背的命令除外;第三,机器人应能保护自己,与第一条违背的命令除外。这是给机器人赋予的伦理性纲领,机器人学术界一直将这三条原则作为机器人开发的准则。

一个简单的注解类

通常情况下,第三方工具不但负责处理特定的注解,本身还提供了这些注解的定义,所以我们通常仅需关注如何使用注解就可以了。但定义注解类本身并不困难,Java提供了定义注解的语法。下面,我们马上着手编写一个简单的注解类,如代码清单7-1所示:

代码清单7-1  NeedTest注解类

[code="java"]package com.baobaotao.aspectj.anno;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) //①声明注解的保留期限

@Target(ElementType.METHOD)//②声明可以使用该注解的目标类型

public @interface NeedTest {//③定义注解

boolean value() default true;//④声明注解成员

}

Java新语法规定使用@interface修饰符定义注解类,如③所示,一个注解可以拥有多个成员,成员声明和接口方法声明类似,这里,我们仅定义了一个成员,如④所示。成员的声明有以下几点限制:


  • 成员以无入参无抛出异常的方式声明,如boolean value(String str)、boolean value() throws Exception等方式是非法的;
  • 可以通过default为成员指定一个默认值,如String level() default "LOW_LEVEL"、int high() default 2是合法的,当然也可以不指定默认值;
  • 成员类型是受限的,合法的类型包括原始类型及其封装类、String、Class、enums、注解类型,以及上述类型的数组类型。如ForumService value()、List foo()是非法的。



在①和②处,我们所看到的注解是Java预定义的注解,称为元注解(Meta-Annotation),它们被Java编译器使用,会对注解类的行为产生影响。@Retention(RetentionPolicy. RUNTIME)表示NeedTest这个注解可以在运行期被JVM读取,注解的保留期限类型在java.lang.annotation.Retention类中定义,介绍如下:


  • SOURCE:注解信息仅保留在目标类代码的源码文件中,但对应的字节码文件将不再保留;
  • CLASS:注解信息将进入目标类代码的字节码文件中,但类加载器加载字节码文件时不会将注解加载到JVM中,也即运行期不能获取注解信息;
  • RUNTIME:注解信息在目标类加载到JVM后依然保留,在运行期可以通过反射机制读取类中注解信息。

  •    Target(ElementType.METHOD)表示NeedTest这个注解只能应用到目标类的方法上,注解的应用目标在java.lang.annotation.ElementType类中定义:
  • TYPE:类、接口、注解类、Enum声明处,相应的注解称为类型注解;
  • FIELD:类成员变量或常量声明处,相应的注解称为域值注解;
  • METHOD:方法声明处,相应的注解称为方法注解;
  • PARAMETER:参数声明处,相应的注解称为参数注解;
  • CONSTRUCTOR:构造函数声明处,相应的注解称为构造函数注解;
  • LOCAL_VARIABLE:局部变量声明处,相应的注解称为局域变量注解;
  • ANNOTATION_TYPE:注解类声明处,相应的注解称为注解类注解,ElementType. TYPE包括ElementType.ANNOTATION_TYPE;
  • PACKAGE:包声明处,相应的注解称为包注解。



如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=),如@NeedTest(true)。注解类拥有多个成员时,如果仅对value成员进行赋值则也可不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号,如DeclareParents (value = "NaiveWaiter", defaultImpl = SmartSeller.class)。注解类可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;此外,所有的注解类都隐式继承于java.lang.annotation.Annotation,但注解不允许显式继承于其他的接口。

我们希望使用NeedTest注解对业务类的方法进行标注,以便测试工具可以根据注解情况激活或关闭对业务类的测试。在编写好NeedTest注解类后,就可以在其他类中使用它了。

使用注解

我们在ForumService中使用NeedTest注解,标注业务方法是否需要测试,如代码清单7-2所示:

代码清单7-2  ForumService:使用注解

[code="java"]package com.baobaotao.aspectj.anno;

public class ForumService {

    @NeedTest(value=true) ①

public void deleteForum(int forumId){

  System.out.println("删除论坛模块:"+forumId);

}

    @NeedTest(value=false) ②

    public void deleteTopic(int postId){

  System.out.println("删除论坛主题:"+postId);

}

}

如果注解类和目标类不在同一个包中,需要通过import引用的注解类。在①和②处,我们使用NeedTest分别对deleteForum()和deleteTopic()方法进行标注。在标注注解时,可以通过以下格式对注解成员进行赋值:

引用
@(=,=,...)


如果成员是数组类型,可以通过{}进行赋值,如boolean数组的成员可以设置为{true,false,true}。下面是几个注解标注的例子:

示例1,多成员的注解:

[code="java"]@AnnoExample(id= 2868724, synopsis = "Enable time-travel",

engineer = "Mr. Peabody",date = "4/1/2007")

示例2,一个成员的注解,成员名为value。可以省略成员名和赋值符号:

[code="java"]@Copyright("2011 bookegou.com All Right Reserved")

示例3,无成员的注解:

[code="java"]@Override

示例4,成员为字符串数组的注解:

[code="java"]@SuppressWarnings(value={"unchecked","fallthrough"})

示例5,成员为注解数组类型的注解:

[code="java"]@Reviews({@Review(grade=Review.Grade.EXCELLENT,reviewer="df
"),     

           @Review(grade=Review.Grade.UNSATISFACTORY,reviewer="eg",             

                    comment="This method needs an @Override annotation")})

@Reviews注解拥有一个@Review注解数组类型的成员,@Review注解类型有三个成员,其中reviewer、comment都是String类型,但comment有默认值,grade是枚举类型的成员。

由于NeedTest注解的保留限期是RetentionPolicy.RUNTIME类型,因此当ForumService被加载到JVM时,仍就可通过反射机制访问到ForumService各方法的注解信息。

访问注解

前面提到过,注解不会直接影响程序的运行,但是第三方程序或工具可以利用代码中的注解完成特殊的任务,间接控制程序的运行。对于RetentionPolicy.RUNTIME保留期限的注解,我们可以通过反射机制访问类中的注解。

在JDK5.0里,Package、Class、Constructor、Method以及Field等反射对象都新增了访问注解信息的方法:T getAnnotation(Class annotationClass),该方法支持通过泛型直接返回注解对象。

下面,我们就通过反射来访问注解,得出ForumService 类中通过@NeedTest注解所承载的测试需求,如代码清单7-3所示:

代码清单7-3  TestTool:访问代码中的注解

[code="java"]package com.baobaotao.aspectj.anno;

import java.lang.reflect.Method;

public class TestTool {

public static void main(String[] args) {

               

               //①得到ForumService对应的Class对象

  Class clazz = ForumService.class;

                //②得到ForumSerivce对应的Method数组

  Method[] methods = clazz.getDeclaredMethods();

  System.out.println(methods.length);

  for (Method method : methods) {

                        //③获取方法上所标注的注解对象

   NeedTest nt = method.getAnnotation(NeedTest. class);

   if (nt != null) {

    if (nt.value()) {

     System.out.println(method.getName() + "()需要测试");

    } else {

     System.out.println(method.getName() + "()不需要测试");

    }

   }

  }

}

}

在③处,通过方法的反射对象,我们获取了方法上所标注的NeedTest注解对象,接着就可以访问注解对象的成员,从而得到ForumService类方法的测试需求。运行以上代码,输出以下的信息:

引用
deleteForum()需要测试

deleteTopic()不需要测试

分享到:
评论

相关推荐

    SpringCloud注解详情XMind文件.zip

    SpringCloud对微服务基础框架Netflix的多个开源组件进行了封装 , 同时又实现了和云端平台以及和SpringBoot开发框架的集成 . ———————————————— 版权声明:本文为CSDN博主「我又不是超人fzx」的原创...

    JAVA OA平台源码(转载)SPRING BOOT....

    【标题】:“JAVA OA平台源码(转载)SPRING BOOT...” 这个开源项目是一个基于Java技术的OA(Office Automation)管理系统的源代码实现,利用了Spring Boot框架进行开发。Spring Boot是Spring生态中的一个核心组件...

    Tomcat 7-9转载资源

    - **Servlet 3.0** 支持:Tomcat 7引入了Servlet 3.0规范,包括异步处理能力,预加载Servlet,以及改进的注解支持。 - **NIO连接器**:提供了非阻塞I/O,提升了高并发场景下的性能。 - **Jasper升级**:JSP编译器...

    java 时间转换(转载)

    在Java编程语言中,时间转换是一项常见的任务,特别是在处理日期和时间数据时。...在实际开发中,确保正确地处理日期和时间,避免出现时区问题,以及有效地进行日期时间的格式化和解析,是至关重要的。

    (转载)自己动手写一个spring

    Spring是Java开发中最流行的框架之一,它以依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)为核心,极大地简化了企业级应用的开发。 首先,我们需要理解什么是依赖注入。...

    SSM整合,参考尚硅谷视频,转载笔记,非原创,侵权删

    SSM整合指的是Spring、SpringMVC和MyBatis三个开源框架的集成,是Java后端开发中的常见技术栈。这一体系结构为开发者提供了强大的控制层、服务层和数据访问层的支持,使得企业级应用的开发更为高效和便捷。下面将...

    java编程事项(转载收集整理版)

    9. **注解(Annotation)**:注解是元数据的一种形式,可提供编译器和运行时有关代码的信息。例如,@Override确保方法是重写父类方法,而@Component用于Spring框架中的依赖注入。 10. **垃圾回收(Garbage ...

    dwr中文教程~转载的,共享一下

    2. **映射**:通过`@RemoteProxy`注解标记Java类或方法,使得它们可被JavaScript访问。 3. **JavaScript API**:DWR生成JavaScript接口,供前端使用,主要API有`DWR Engine`、`Call`、`Batch`等。 4. **通信**:...

    [转载] JAXB中Java对象和XML之间的转换

    JAXB,全称为Java Architecture for XML Binding,是Java平台中用于在XML和Java对象之间进行映射的标准技术。...通过理解并熟练掌握JAXB的核心概念和用法,开发者可以更便捷地实现XML文档的读写,提高开发效率。

    jsr168 portlet(struts2+spring2.5+hibernate3.3)(转载)

    Spring 2.5版本引入了更多改进,如支持注解配置、更灵活的AOP、XML Schema-based配置等,增强了应用程序的可维护性和可测试性。 3. **Hibernate3.3**:Hibernate是一个对象关系映射(ORM)框架,它简化了数据库操作...

    JDK 6.2.3文文档.rar

    JDK6新特性目录导航: ...版权声明:本文为CSDN博主「念念就忘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_40926603/article/details/84970283

    基于SIP开发软件电话的一些资源(转自YOUTOO)

    所以我们这里只是用它快速开发一个SIP终端,用来更方便地学习oSIP,要想真正掌握SIP的开发,需要掌握oSIP并熟读RFC文档才行,exoSIP不是我们的最终学习目的),通过成功编译运行一个自己动手开发出的程序,再...

    java编程思想习题及答案

    8. **枚举与注解**:了解枚举类型和注解的使用,它们在代码规范、元数据标注等方面发挥着重要作用。 9. **泛型**:理解泛型的概念,知道如何使用泛型类、接口和方法,以增强代码的类型安全性和重用性。 10. **设计...

    java事例集合1

    【描述】中的"事例集合1(转载)"表明这些内容可能来源于网络,可能是某个开发者或教育者收集并整理的Java编程实例,目的是帮助学习者通过实际操作来理解Java编程。而"看韩剧www.pigkrtv.com"这部分看起来像是无关的...

    leetcode下载-java-eight-part:『Java八股文』Java面试套路,Java进阶学习,打破内卷拿大厂Offer,升职加薪

    版权说明:所有文章都已首发我的微信公众号,如果需要转载可以授权,恶意抄袭我会不惜一切代价维护权益,希望同行一起维护良好的创作环境。 :hot_beverage: Java Java入门面试题 Java并发编程(J.U.C) :thumbs_up: ...

    springmybatis

    MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个...

Global site tag (gtag.js) - Google Analytics