• Java-注解(@Annotation)


    一、缘由

        上篇也提到过要开spring cloud系列,但是避免不了就是spring boot,那针对这个我们首先要明白的就是spring boot启动到底帮我做了那些事,明白这些我们后面使用起来的时候就会得心应手,但是你会发现一个问题,那就是spring boot就是通过这些注解去加载的,所以这个地方我要来聊聊注解,当然spring也好多都是注解去实现的,这样我们就要更改明白注解到底是帮我们做了哪些事。

    二、什么是注解以及注解的作用(Annotation):

        注解是插入到代码中的元数据,JDK5.0以后的版本引入。注解必须有编译器或者虚拟机来解析它,才能发挥自己的作用,它可以生成文件,可以执行编译时进行测试和验证格式等等。因为本质上,注解是一种特殊的接口,程序可以通过反射来获取指定程序元素的注解对象,然后通过注解对象来获取注解里面的元数据。

        注解的作用:

        1.编写文档:通过代码里标识的元数据生成文档;

        2.代码分析:通过代码里标识的元数据对代码进行分析;

        3.编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查;

    二、注解的类型

        1.内置注解

        @Override:表示当前的方法可以覆盖父类中的方法;

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    View Code

        @Deprecated:用于标注该方法已经过时,当程序员调用的时候,编译器会发生警告的信息;

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
    public @interface Deprecated {
    }
    View Code

       @SuppressWarnnings:用于关闭不当的编译器警告;

    @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface SuppressWarnings {
        String[] value();
    }
    View Code

       内部有个string数组,简单的说一下改数组接收的几个常用的几个参数:

       1.deprecation:使用了由@Deprecated修饰的类或方法时的警告;

       2.unchecked:执行了未检查的转换时的警告;

       3.path:在类路径、源文件路径等中有不存在的路径时的警告;

       4.all:所有情况的警告;

       5.剩下的参考http://www.cnblogs.com/fsjohnhuang/p/4040785.html

       接下来简单的介绍下上面3种使用的方法:

    public class Person {
    
        @Deprecated
        public void getCountryName(){
            System.out.printf("我是地球人");
        }
        
    }
    
    public class ChinaPerson extends Person {
        @SuppressWarnings("deprecation")
        @Override
        public void getCountryName(){
            System.out.printf("我是中国人");
        }
    
    
    }
    public class Main {
    
        public static void main(String[] args) {
            ChinaPerson chinaPerson=new ChinaPerson();
            chinaPerson.getCountryName();
        }
    }
    View Code

       2.元注解

       @Target:用来约束注解可以应用到的地方:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Target {
        /**
         * Returns an array of the kinds of elements an annotation type
         * can be applied to.
         * @return an array of the kinds of elements an annotation type
         * can be applied to
         */
        ElementType[] value();
    }
    View Code

       该注解可以接收一个ElementType数组,该类型是个枚举类型可以接收如下参数:

       1.PACKAGE:标明注解可以用于包声明;

       2.CONSTRUCTOR:标明注解可以用于构造函数声明;

       3.PARAMETER:标明该注解可以用于参数声明;

       4.METHOD:标明该注解可以用于方法声明;

       5.FIELD:标明该注解可以用于字段(域)声明,包括enum实例;

       6.TYPE:标明该注解可以用于类、接口(包括注解类型)或enum声明;

       7.LOCAL_VARIABLE:标明注解可以用于局部变量声明;

       8.ANNOTATION_TYPE:标明注解可以用于注解声明(应用于另一个注解上);

       9.TYPE_PARAMETER:标明注解可以用于类型参数声明(1.8新加入);

       10.TYPE_USE:类型使用声明(1.8新加入);

       @Retention:用来约束注解的生命周期:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Retention {
        /**
         * Returns the retention policy.
         * @return the retention policy
         */
        RetentionPolicy value();
    }
    View Code

       可接收的参数如下:

       1.SOURCE:在源文件中有效,被编译器丢弃;

       2.CLASS:在class文件中有效,会被VM丢弃,当没有定义CLASS默认CLASS;

       3.RUNTIME:在运行时有效,可以通过反射机制读取注解的信息;

       @Documented:被修饰的注解会生成到javadoc中

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Documented {
    }
    View Code

       @Inherited:允许子类继承父类的注解,即它所标注的Annotation将具有继承性,通过使用@Inherited,可以让子类Class对象使用getAnnotations()获取父类被@Inherited修饰的注解

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.ANNOTATION_TYPE)
    public @interface Inherited {
    }
    View Code

       3.自定义注解

       使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型。可以通过default来声明参数的默认值。

       接下来我们做个简单的案例来体验下:

    import java.lang.annotation.*;
    
    /**
     * Created by wangt on 2018/6/17.
     */
    @Inherited
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Table {
        String value() default "";
    }
    
    import java.lang.annotation.*;
    
    /**
     * Created by wangt on 2018/6/17.
     */
    @Inherited
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Column {
        String value() default "";
    }
    
    
    /**
     * Created by wangt on 2018/6/17.
     */
    @Table("sutdent")
    public class StudentDto {
    
        @Column("id")
        private String id;
    
        @Column("username")
        private String name;
    
        public StudentDto(String id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }
    
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * Created by wangt on 2018/6/17.
     */
    public class Test {
        public static void main(String[] args){
            StudentDto studentDto=new StudentDto("1","wtz");
            StudentDto studentDto2=new StudentDto("2","www");
            String sql = assembleSqlFromObj(studentDto);
            String sql1 = assembleSqlFromObj(studentDto2);
            System.out.println(sql);
            System.out.println(sql1);
        }
    
        private static String assembleSqlFromObj(Object object) {
            Table table = object.getClass().getAnnotation(Table.class);
            StringBuffer sbSql = new StringBuffer();
            String tableName = table.value();
            sbSql.append("select * from " + tableName + " where 1=1 ");
            Field[] fileds = object.getClass().getDeclaredFields();
            for (Field f : fileds) {
                String fieldName = f.getName();
                String methodName = "get" + fieldName.substring(0, 1).toUpperCase()
                        + fieldName.substring(1);
                try {
                    Column column = f.getAnnotation(Column.class);
                    if (column != null) {
                        Method method = object.getClass().getMethod(methodName);
                        String value = (String) method.invoke(object);
                        if (value != null && !value.equals("")) {
                            if (!isNum(column.value()) && !isNum(value)) {
                                // 判断参数是不是 in 类型参数 1,2,3
                                if (value.contains(",")) {
                                    sbSql.append(" and " + column.value() + " in (" + value + ") ");
                                } else {
                                    sbSql.append(" and " + column.value() + " like '%" + value + "%' ");
                                }
                            } else {
                                sbSql.append(" and " + column.value() + "=" + value + " ");
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return sbSql.toString();
        }
    
        public static boolean isNum(String target) {
            boolean isNum = false;
            if (target.toLowerCase().contains("id")) {
                isNum = true;
            }
            if (target.matches("\d+")) {
                isNum = true;
            }
            return isNum;
        }
    
    
    }
    View Code

      这个自己想想是啥原理,,哈哈不懂问我。

    四、总结

     Java的注解原理是Java的反射机制,要是自定义注解那块没有看懂的话,再去读读反射把,这是一个很重要的东西,有机会我也会写一篇反射方面的;

     欢迎大家加群:438836709,有问题可以咨询我

     欢迎大家关注我微信公众号:

     

  • 相关阅读:
    Android清单文件详解(四) ---- backupAgent的用法
    Android清单文件详解(一) ---- 一切从<manifest>开始
    Android OpenGL ES(九)----构建几何物体
    Android OpenGL ES(八)----纹理编程框架
    Android OpenGL ES(七)----理解纹理与纹理过滤
    Android OpenGL ES(六)----进入三维在代码中创建投影矩阵和旋转矩阵
    Android OpenGL ES(五)----进入三维正交投影和透视投影推导
    Android OpenGL ES(四)----调整屏幕的宽高比
    获取验证码按钮点击后,一分钟内不可继续点击
    选择本地图片后,上传前显示在界面上,实现实时预览
  • 原文地址:https://www.cnblogs.com/wtzbk/p/9192265.html
Copyright © 2020-2023  润新知