精华内容
下载资源
问答
  • 前言在android开发中有很多运用到注解处理器...这里主要讲解自定义注解处理器的原理。知识点在自定义注解时,一般需要掌握以下几个知识点:AbstractProcessor相关知识auto-service相关知识javapoet相关知识A...

    前言

    在android开发中有很多运用到注解处理器(annotation processing)的框架,如常见的Butterknife,Dagger2,EventBus等,运用这些注解处理器框架大大简化了我们的代码。这里主要讲解自定义注解处理器的原理。

    知识点

    在自定义注解时,一般需要掌握以下几个知识点:

    AbstractProcessor相关知识

    auto-service相关知识

    javapoet相关知识

    AbstractProcessor简介

    在《深入理解Java虚拟机》中早期(编译器)优化章节中,当通过javac将.java文件编译成.class文件时。编译过程大致可以分为3个过程:

    解析与填充符号表过程

    插入式注解处理器的注解处理过程

    分析与字节码生成过程

    而插入式注解处理器的注解处理过程主要就是对AbstractProcessor这个类的调用。所以,当我们自定义这个类的子类的时候,在编译器就会执行这个类中的方法。

    对注解(Annotation)的支持时从JDK1.5开始的,但这个时候的注解只在运行期间发挥作用。从JDK1.6开始,提供了插入式注解处理器的标准API在编译期间对注解进行处理。这也就要求我们依赖的JDK版本应该高于1.6(包括1.6)。

    在javac源码中,插入式注解处理器的初始化过程是在initProcessAnnotations()方法中完成的,而它的执行过程则是在processAnnotations()方法中完成的,这个方法判断是否有新的注解处理器需要执行,如果有的话,通过com.sun.tools.javac.processing.JavacProcessingEnvironment类的doProcessing()方法生成一个新的JavaCompiler对象对编译的后续步骤进行处理。

    上面介绍了注解处理器在javac源码中的调用过程,而在具体的通过注解处理器API实现一个编译器插件,需要继承抽象类javax.annotation.processing.AbstractProcessor,重写抽象方法process(),这个方法在javac编译器在执行注解处理器代码时调用。这个方法有两个参数,第一个参数表示注解处理器所有处理的注解集合,第二个参数roundEnvironment表示当前这个Round中的语法树节点,每个语法树节点在这里表示一个Element。这里的Element包括如下元素:包(PACKAGE)、枚举(ENUM)、类(CLASS)、注解(ANNOTATION_TYPE)、接口(INTERFACE)等。

    由此可知,我们在android开发中使用的AbstractProcessor这个类是JDK通过javac编译的时候用来处理注解的。而android sdk中删除了这个类,所以我们需要通过创建java library库来获取这个类。至此,我们大概理解了AbstractProcessor这个类执行时机和创建方法。

    现在自定义AbstractProcessor的子类已经有了,但是要想在编译时期被执行,需要向javac注册我们这个自定义的注解处理器(即将这个库变成jar包的形式),这样,在javac编译时,才会调用到我们这个自定义的注解处理器方法。那么如何设置成jar包了。这就引出下面的auto-service库了。

    auto-service简介

    正常情况下,向javac中注册自定义的处理器的步骤如下:

    在src/main目录下创建resources/META-INF/services/javax.annotation.processing.Processor文件。

    在javax.annotation.processing.Processor中写入自定义的Processor的全名,如果有过个Processor的话,每行写一个。如下:

    com.soulmate.processor.MyProcessor

    复制代码

    这样,在javac编译时,在处理注解处理器的时候就会执行我们自定义的注解处理器。

    上面是正常的一种人工设置的方法,但是每次这样配置的话一个是写起来很麻烦,还有如果我修改了自定义的AbstractAnnotation子类的类名的话,可能会因为忘了修改而导致错误,而auto-service这个库就是为了解决这个问题。它可以自动完成上面需要添加的步骤,只需要在自定义的注解处理器类上面添加@AutoService(Processor.class)这个注解就可以了。这样也可以避免上面所说的问题。具体使用可以看一下官方文档。

    到这里在编译的时候自定义的注解处理器已经可以被执行了,那么javapoet是干嘛的了?其实在自定义注解处理器的process()方法中,我们经常需要生成需要的java类,这个可以参考ButterKnife框架中的ButterKnifeProcessor类中process()方法,在这个方法中就是使用javapoet来生成需要的类,生成的类中定义了findViewById()方法。

    javapoet简介

    javapoet是square开源的一个java生成库,官网解释为:

    JavaPoet is a Java API for generating `.java` source files

    复制代码

    javapoet的使用比较简单,官方文档给出了非常详细的讲解。所以这里就不过多的介绍,具体的使用可以看官网的示例。

    总结

    到这里关于整个自定义注解处理器的流程就介绍完了,这里主要介绍的是编译器的注解处理器。包括整个编译时注解在源码中的调用流程。

    展开全文
  • Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。注解处理器类库(java.lang.reflect.AnnotatedElement):Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父...

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。

    注解处理器类库(java.lang.reflect.AnnotatedElement):

    Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

    Class:类定义

    Constructor:构造器定义

    Field:累的成员变量定义

    Method:类的方法定义

    Package:类的包定义

    java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

    AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

    方法1: T getAnnotation(Class annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

    方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。

    方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.

    方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

    一个简单的注解处理器:

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    /***********注解声明***************/

    /**

    * 水果名称注解

    * @author peida

    *

    */

    @Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface FruitName {

    String value() default "";

    }

    /**

    * 水果颜色注解

    * @author peida

    *

    */

    @Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface FruitColor {

    /**

    * 颜色枚举

    * @author peida

    *

    */

    public enum Color{ BULE,RED,GREEN};

    /**

    * 颜色属性

    * @return

    */

    Color fruitColor() default Color.GREEN;

    }

    /**

    * 水果供应者注解

    * @author peida

    *

    */

    @Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface FruitProvider {

    /**

    * 供应商编号

    * @return

    */

    public int id() default -1;

    /**

    * 供应商名称

    * @return

    */

    public String name() default "";

    /**

    * 供应商地址

    * @return

    */

    public String address() default "";

    }

    /***********注解使用***************/

    public class Apple {

    @FruitName("Apple")

    private String appleName;

    @FruitColor(fruitColor=Color.RED)

    private String appleColor;

    @FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")

    private String appleProvider;

    public void setAppleColor(String appleColor) {

    this.appleColor = appleColor;

    }

    public String getAppleColor() {

    return appleColor;

    }

    public void setAppleName(String appleName) {

    this.appleName = appleName;

    }

    public String getAppleName() {

    return appleName;

    }

    public void setAppleProvider(String appleProvider) {

    this.appleProvider = appleProvider;

    }

    public String getAppleProvider() {

    return appleProvider;

    }

    public void displayName(){

    System.out.println("水果的名字是:苹果");

    }

    }

    /***********注解处理器***************/

    public class FruitInfoUtil {

    public static void getFruitInfo(Class> clazz){

    String strFruitName=" 水果名称:";

    String strFruitColor=" 水果颜色:";

    String strFruitProvicer="供应商信息:";

    Field[] fields = clazz.getDeclaredFields();

    for(Field field :fields){

    if(field.isAnnotationPresent(FruitName.class)){

    FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);

    strFruitName=strFruitName+fruitName.value();

    System.out.println(strFruitName);

    }

    else if(field.isAnnotationPresent(FruitColor.class)){

    FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);

    strFruitColor=strFruitColor+fruitColor.fruitColor().toString();

    System.out.println(strFruitColor);

    }

    else if(field.isAnnotationPresent(FruitProvider.class)){

    FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);

    strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();

    System.out.println(strFruitProvicer);

    }

    }

    }

    }

    /***********输出结果***************/

    public class FruitRun {

    /**

    * @param args

    */

    public static void main(String[] args) {

    FruitInfoUtil.getFruitInfo(Apple.class);

    }

    }

    ====================================

    水果名称:Apple

    水果颜色:RED

    供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦

    48304ba5e6f9fe08f3fa1abda7d326ab.png

    Java注解的基础知识点(见下面导图)基本都过了一遍,下一篇我们通过设计一个基于注解的简单的ORM框架,来综合应用和进一步加深对注解的各个知识点的理解和运用。

    6bb4285a66c0c603145673464f02e7d8.png

    展开全文
  • 这里就主要论述一下annotation的用法和自定义注解处理器。当在创建描述符性质的类或接口时,有大量重复性的工作时候,就可以利用注解来实现。基本语法:Java目前包括三种标准注解和四种元注解。元注解主要负责注解...

    前言:

    在J2EE中,注解使得开发更加便利,省去了生成XML文件的过程,在Hibernate实体声明中,可以简简单单的用几个注解就可以免去生成一个XML的文件操作。这里就主要论述一下annotation的用法和自定义注解处理器。当在创建描述符性质的类或接口时,有大量重复性的工作时候,就可以利用注解来实现。

    基本语法:

    Java目前包括三种标准注解和四种元注解。元注解主要负责注解其他注解的。

    三种标准注解:

    @Override,表示当前的方法定义覆盖了父类中的方法。必须要有相同的方法签名即(方法名,参数类型,参数顺序,参数个数)都一样。否则在编译过程中发出错误提示。

    @Deprecated,对不应该再使用的方法添加注解,当使用这个方法的时候,会在编译时候显示提示信息。

    @SuppressWarnings,关闭不当的编译器报警信息

    四种元注解:

    @Target,表示该注解可以用什么地方。

    如CONSTRUCTOR,构造器声明;FIELD,域声明;METHOD,方法声明;TYPE,类,接口或enum声明

    @Retention,表示需要在什么级别保存该注解信息。

    如SOURCE,注解将被编译器丢弃;CLASS,注解在class文件可用,但会被VM丢弃

    RUNTIME,VM将在运行期间也保留注解,可以使用反射机制读取注解信息

    @Documented,将此注解包含到Javadoc中。

    @Inherited,允许子类继承父类的注解。

    定义注解:

    自定义注解是以@interface为标志的。如同一个接口的定义,这里面定义的每个方法名,就是使用注解时候的元素名,方法的返回值就是元素的类型,可以利用default来声明默认值,不过对于非基本类型,不能设置为null为默认值,一般对于字符串使用空字符串作为其默认值。

    如下所示:

    package whut.annotation;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    //定义一个注解

    @Target(ElementType.METHOD)//定义该注解将应用于什么地方,方法或者域

    @Retention(RetentionPolicy.RUNTIME)//定义该注解在哪一个级别可用

    public @interface UseCase {

    //注解元素,可以指定默认值,在使用注解的时候,可以直接给元素赋值如id=5

    public int id();

    public String description() default "no description";

    //利用枚举来设置参数类型

    public enum ParameterType { STRING, SHORT, INT, BOOL, LONG, OBJECT };

    // 默认值,在使用注解的时候,只需要为元素赋值

    public ParameterType type() default ParameterType.STRING;

    }

    使用注解:

    在类中任意的域值前,或者方法前等直接@注解名,如@UseCase(id=5),使用注解的过程中,必须对于没有设置默认值的元素进行赋值操作,对于每个元素进行按照名-值对的方式赋值。如果在注解定义中有名为value的元素,并且它是唯一需要赋值的,可以直接在括号里给出value所需要的值。

    注解是不能继承的。

    下面是一个基本的利用非apt实现的注解处理器模型。

    这个模型可以注解实体,进行数据库的映射建表操作。是最最基本的操作。

    注解定义:将四个注解名是在不同的文件中。

    package whut.annotationDB;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    //定义字段的约束

    public @interface Constraints {

    boolean primaryKey() default false;

    boolean allowNull() default true;

    boolean unique() default false;

    }

    package whut.annotationDB;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(ElementType.TYPE)//类,接口或enum

    @Retention(RetentionPolicy.RUNTIME)

    //定义表名的注解

    public @interface DBTable {

    public String name() default "";

    }

    ///

    package whut.annotationDB;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(ElementType.FIELD)//类,接口或enum

    @Retention(RetentionPolicy.RUNTIME)

    public @interface SQLInteger {

    String name() default "";

    //嵌套注解的功能,将column类型的数据库约束信息嵌入其中

    Constraints constraints() default @Constraints;

    }

    ///

    package whut.annotationDB;

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    @Target(ElementType.FIELD)//类,接口或enum

    @Retention(RetentionPolicy.RUNTIME)

    public @interface SQLString {

    int value() default 0;

    String name() default "";

    //注解元素中引用别的注解,

    Constraints constraints() default @Constraints;

    }

    实体使用注解:这里是运用了运行时候处理注解,所以RetentionPolicy.RUNTIME

    package whut.annotationDB;

    @DBTable(name="MEMBER")

    public class Member {

    //在使用注解过程中,如果有元素是value,并且只有value需要赋值,

    //则只需要在()中将值写入

    @SQLString(30)

    private String firstName;

    @SQLString(50)

    private String lastName;

    @SQLInteger

    private Integer age;

    @SQLString(value=30,constraints=@Constraints(primaryKey=true))

    private String handle;

    public String getFirstName() {

    return firstName;

    }

    public void setFirstName(String firstName) {

    this.firstName = firstName;

    }

    public String getLastName() {

    return lastName;

    }

    public void setLastName(String lastName) {

    this.lastName = lastName;

    }

    public Integer getAge() {

    return age;

    }

    public void setAge(Integer age) {

    this.age = age;

    }

    public String getHandle() {

    return handle;

    }

    public void setHandle(String handle) {

    this.handle = handle;

    }

    }

    具体的非apt实现的注解处理器:package whut.annotationDB;

    import java.lang.annotation.Annotation;

    import java.lang.reflect.Field;

    import java.sql.Connection;

    import java.sql.DriverManager;

    import java.sql.PreparedStatement;

    import java.sql.SQLException;

    import java.util.ArrayList;

    import java.util.List;

    public class TableCreator {

    public Connection getConnection() {

    String user = "root";

    String password = "";

    String serverUrl = "jdbc:mysql://localhost:3306/carrent?user=root&password=";

    try {

    Class.forName("com.mysql.jdbc.Driver");

    Connection con = DriverManager.getConnection(serverUrl, user,

    password);

    return con;

    } catch (Exception e) {

    e.printStackTrace();

    return null;

    }

    }

    //实现创建表

    public static void main(String[] args) {

    TableCreator tc = new TableCreator();

    tc.executeCreateDB(Member.class);

    }

    public void executeCreateDB(Class> entity) {

    String sqlStr = explainAnnotation(entity);

    Connection con = getConnection();

    PreparedStatement psql = null;

    if (con != null && !sqlStr.equals("error")) {

    try {

    psql = con.prepareStatement(sqlStr);

    psql.execute();

    } catch (SQLException e) {

    e.printStackTrace();

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    try {

    if (psql != null)

    psql.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    try {

    if (con != null)

    psql.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    }

    } else

    System.out.println("failure to...");

    }

    // 真正的处理器,Class>必须用这个表明

    public String explainAnnotation(Class> entity) {

    // 获取指定类型的注解

    DBTable dbtable = entity.getAnnotation(DBTable.class);

    if (dbtable == null) {

    System.out.println("No DBTable annotation in class"

    + entity.getName());

    return "error";

    } else {

    String tableName = dbtable.name();// 获取注解name值,即表名称

    // 当没有设置name值,直接利用类的名作为表名

    if (tableName.length() < 1)

    tableName = entity.getName().toUpperCase();// 转换大写

    // 准备处理字段注解

    List columnsDefs = new ArrayList();

    // 获取该类的所有字段

    for (Field field : entity.getDeclaredFields()) {

    String columnName = null;

    // 获取该字段所有的注解

    Annotation[] anns = field.getDeclaredAnnotations();

    // Annotation[] anns=field.getAnnotations();

    // 当有注解的时候

    if (anns.length >= 1) {

    // 判断注解的类型

    if (anns[0] instanceof SQLInteger) {

    SQLInteger sInt = (SQLInteger) anns[0];

    // 当没有name时候,将字段大写为列名

    if (sInt.name().length() < 1)

    columnName = field.getName().toUpperCase();

    else

    columnName = sInt.name();

    columnsDefs.add(columnName + " INT"

    + getConstraints(sInt.constraints()));

    }

    if (anns[0] instanceof SQLString) {

    SQLString sString = (SQLString) anns[0];

    // 当没有name时候,将字段大写为列名

    if (sString.name().length() < 1)

    columnName = field.getName().toUpperCase();

    else

    columnName = sString.name();

    columnsDefs.add(columnName + " VARCHAR("

    + sString.value() + ")"

    + getConstraints(sString.constraints()));

    }

    }

    }

    StringBuilder createDB = new StringBuilder("CREATE TABLE "

    + tableName + "(");

    for (String cols : columnsDefs)

    createDB.append(" " + cols + ",");

    // 移除最后一个,号

    String tableSQL = createDB.substring(0, createDB.length() - 1)

    + ");";

    // 输出创建表的过程

    System.out.println("Table Creation SQL is:\n" + tableSQL);

    return tableSQL;

    }

    }

    // 返回指定的约束

    public String getConstraints(Constraints con) {

    String constras = "";

    if (!con.allowNull())

    constras += " NOT NULL";

    if (con.primaryKey())

    constras += " PRIMARY KEY";

    if (con.unique())

    constras += " UNIQUE";

    return constras;

    }

    }

    展开全文
  • Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。注解处理器类库(java.lang.reflect.AnnotatedElement):Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父...

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。

    注解处理器类库(java.lang.reflect.AnnotatedElement):

    Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

    Class:类定义

    Constructor:构造器定义

    Field:累的成员变量定义

    Method:类的方法定义

    Package:类的包定义

    java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

    AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

    方法1: T getAnnotation(Class annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

    方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。

    方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.

    方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

    一个简单的注解处理器:

    /***********注解声明***************/

    /*** 水果名称注解

    *@authorpeida

    **/@Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documentedpublic @interfaceFruitName {

    String value()default "";

    }/*** 水果颜色注解

    *@authorpeida

    **/@Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documentedpublic @interfaceFruitColor {/*** 颜色枚举

    *@authorpeida

    **/

    public enumColor{ BULE,RED,GREEN};/*** 颜色属性

    *@return

    */Color fruitColor()defaultColor.GREEN;

    }/*** 水果供应者注解

    *@authorpeida

    **/@Target(ElementType.FIELD)

    @Retention(RetentionPolicy.RUNTIME)

    @Documentedpublic @interfaceFruitProvider {/*** 供应商编号

    *@return

    */

    public int id() default -1;/*** 供应商名称

    *@return

    */

    public String name() default "";/*** 供应商地址

    *@return

    */

    public String address() default "";

    }/***********注解使用***************/

    public classApple {

    @FruitName("Apple")privateString appleName;

    @FruitColor(fruitColor=Color.RED)privateString appleColor;

    @FruitProvider(id=1,name="陕西红富士集团",address="陕西省西安市延安路89号红富士大厦")privateString appleProvider;public voidsetAppleColor(String appleColor) {this.appleColor =appleColor;

    }publicString getAppleColor() {returnappleColor;

    }public voidsetAppleName(String appleName) {this.appleName =appleName;

    }publicString getAppleName() {returnappleName;

    }public voidsetAppleProvider(String appleProvider) {this.appleProvider =appleProvider;

    }publicString getAppleProvider() {returnappleProvider;

    }public voiddisplayName(){

    System.out.println("水果的名字是:苹果");

    }

    }/***********注解处理器***************/

    public classFruitInfoUtil {public static void getFruitInfo(Class>clazz){

    String strFruitName=" 水果名称:";

    String strFruitColor=" 水果颜色:";

    String strFruitProvicer="供应商信息:";

    Field[] fields=clazz.getDeclaredFields();for(Field field :fields){if(field.isAnnotationPresent(FruitName.class)){

    FruitName fruitName= (FruitName) field.getAnnotation(FruitName.class);

    strFruitName=strFruitName+fruitName.value();

    System.out.println(strFruitName);

    }

    elseif(field.isAnnotationPresent(FruitColor.class)){

    FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);

    strFruitColor=strFruitColor+fruitColor.fruitColor().toString();

    System.out.println(strFruitColor);

    }

    elseif(field.isAnnotationPresent(FruitProvider.class)){

    FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);

    strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();

    System.out.println(strFruitProvicer);

    }

    }

    }

    }/***********输出结果***************/

    public classFruitRun {/***@paramargs*/

    public static voidmain(String[] args) {

    FruitInfoUtil.getFruitInfo(Apple.class);

    }

    }====================================水果名称:Apple

    水果颜色:RED

    供应商编号:1 供应商名称:陕西红富士集团 供应商地址:陕西省西安市延安路89号红富士大厦

    Java注解的基础知识点(见下面导图)基本都过了一遍,下一篇我们通过设计一个基于注解的简单的ORM框架,来综合应用和进一步加深对注解的各个知识点的理解和运用。

    6bb4285a66c0c603145673464f02e7d8.png

    展开全文
  • 如果在第 2 步调用注解处理器过程中生成了新的源文件,那么编译器将重复第 1、2 步,解析并且处理新生成的源文件。每次重复我们称之为一轮(Round)。注解处理是按照 Round 的顺序进行的。在每次进行 Round 操作时,...
  • 在之前的《简单实现ButterKnife的注解功能》中,使用了运行时的注解实现了通过编写注解绑定View与xml。由于运行时注解需要在Activity初始化中进行绑定操作,调用了大量反射相关代码,在界面复杂的情况下,使用这种...
  • 本篇回答附带视频教程正文注解(Annotation)概念注解Java SE 5.0版本开始引入的概念,它是对java源代码的说明,是一种元数据(描述数据的数据)。注解和注释的不同注释注释是对代码的说明,给代码的读者看,便于帮...
  • Java中的注解-自定义注解处理器 Hello,大家好,上篇文章Java中的注解-自定义注解和大家分享了如何自定义一个注解,文章最后也和大家分享了自定义注解如何使用,除了和Spring整合使用外,没有注解处理器,那自定义...
  • Java注解annotation用法和自定义注解处理器 解压密码 www.jiangyea.com
  • Java注解与自定义注解处理器

    万次阅读 2016-08-11 16:24:20
    所以本文就注解与自定义注解处理器来学习注解。
  • Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。 注解处理器类库(java.lang.reflect.AnnotatedElement):  Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Ann...
  • Java注解是在Java SE5中被引入进来的,在Java中内置了三种注解以及四种元注解。 内置注解 内置注解 说明 @Override 表示当前的方法定义将覆盖超类中的方法,如果方法名或者参数有误,那么编...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 502
精华内容 200
关键字:

java自定义注解处理器

java 订阅