注解

简介

注解就相当于是标签,比如这几年比较流行给明星添标签,霍建华的“老干部”,黄磊的“好男人”等,但是标签并不是代码的一部分,它本身不会对代码逻辑有任何的改变,需要开发者本身编写代码去处理。就像黄磊一样,大家给它添了一个“好男人”的标签,那么他真的就是好男人吗?或许是,标签是对事物行为的 >某些角度< 的评价与解释

注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。
注解有许多用处,主要如下:
提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。
运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

元注解:注解中的注解

语法要求

使用语法:

@注解名(成员名 = 成员值, ...)

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Descr {
    String desc();
    String author() defalut = "imain";
    // ...
}
  • @Target:执行自定义注解的使用位置

    • ElementType.TYPE:允许注解在
    • ElementType.METHOD:允许注解在方法
    • ElementType.FIELD:允许注解在字段
    • ElementType.CONSTRUCTOR:允许注解在构造函数
    • ElementType.LOCAL_VARIABLE:允许注解在局部变量
    • ElementType.PACKAGE:允许注解在
    • ElementType.PARAMETER:允许注解在参数
    • ...
  • @Retention:注解生效的时段

    • RetentionPolicy.SOURCE:只在源码中显示,编译时会丢弃
    • RetentionPolicy.CLASS:编译时会记录到.class中,运行时忽略
    • RetentionPolicy.RUNTIME:运行时有效,可以通过反射读取
  • @Inherited:允许子类继承
  • @Documented:生成Doc注释

定义要求:

  • 成员类型受限,合法的类型只包括基本类型StringClassAnnotationEnumeration
  • 如果注解只有一个成员时,则成员必须取名为value(),使用时可以忽略成员名和赋值号(=),这是规范
  • 可以没有成员,没有成员的注解叫标记注解
  • 不能有参数和异常

解析注解

通过反射获取类、函数、成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}
@Table("user")
public class Person {

    @Column("id")
    private Integer id;

    @Column("name")
    private String name;

    @Column("age")
    private Integer age;

    @Column("email")
    private String email;
    
    // 省略 setter getter
}
public class Test {

    public static void main(String[] args) {
        /**
         * 有一个实体类,需要通过注解实现SQL查询
         *
         * 两个注解:@Table - @Column
         */
        Person person1 = new Person();
        person1.setId(10001); // 根据ID查询用户
        person1.setName("曾小晨,曾曾曾");
        person1.setAge(21);

        Person person2 = new Person();
        person2.setName("曾小晨"); // 根据名字查询用户

        Person person3 = new Person();
        person3.setEmail("704729872@qq.com,ibubbo@qq.com"); // 根据邮箱查询用户

        selectSQL(person1);
    }
    
    public static <T> void selectSQL(T obj) {
        // 简单条件拼接
        StringBuilder builder = new StringBuilder("select * from ");

        // 复杂条件拼接
        StringBuilder containerBuilder = new StringBuilder();

        // 装载复杂条件
        Map map = new HashMap();

        Class<?> aClass = obj.getClass();

        // 判断Class对象里是否包含了 @Table 注解
        boolean isTExists = aClass.isAnnotationPresent(Table.class);
        if (isTExists) {
            // 如果包含了就取出 @Table 的值
            String tableName = aClass.getAnnotation(Table.class).value();
            builder.append(tableName).append(" where 1 = 1");

            // 遍历所有的字段
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                // 判断字段上是否有 @Column 注解
                boolean isFExists = field.isAnnotationPresent(Column.class);
                if (isFExists) {
                    String fieldName = field.getAnnotation(Column.class).value();

                    // 得到字段的值
                    try {
                        Method method = aClass.getMethod(
                                "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1)
                        );
                        Object fieldValue = method.invoke(obj);
                        
                        if (!((null == fieldValue) ||
                                (fieldValue instanceof Integer && (Integer) fieldValue == 0))) {
                            // 如果字段值不等于 null 才拼接
                            if (fieldValue instanceof String) {
                                // 只考虑字符串
                                if (((String) fieldValue).contains(",")) {


                                    String[] split = ((String) fieldValue).split(",");

                                    containerBuilder.append(fieldName).append(" in (");
                                    for (String str : split) {
                                        containerBuilder.append("'").append(str).append("'").append(","); // contoin
                                    }
                                    // 去掉最后一个逗号
                                    containerBuilder.deleteCharAt(containerBuilder.length() - 1).append(")");
                                    map.put("in", containerBuilder.toString());
                                } else {
                                    builder.append(" and ").append(fieldName).append(" = ").append("'").append(fieldValue).append("'");
                                }
                            } else if (fieldValue instanceof Integer) {
                                builder.append(" and ").append(fieldName).append(" = ").append(fieldValue);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        if (!map.isEmpty()) {
            builder.append(" and ").append(map.get("in"));
        }
        System.out.println(builder.toString());
    }
}
Last modification:March 1st, 2018 at 08:54 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment