• 【iMooc】全面解析java注解


    在慕课上学习了一个关于java注解的课程,下面是笔记以及一些源码。

    Annotation——注解

    1.JDK中的注解

    JDK中包括下面三种注解:

    @Override:标记注解(marker annotation),重写,父类写的方法,如果子类继承了父类,就要重写父类的方法。

    @Deprecated:表示过时的语法加上这个注解之后,该方法上会出现一道删除线

    @SuppressWarning:忽略警告,压制警告。如果某语句前面出现警告,加上这个注解,警告就会消失。

    举例如下:

    父类 一个Person接口: @Deprecated表示该方法过时。

    package com.ann.test;
    
    public interface Person {
        public String name();
    
        public int age();
    
        @Deprecated
        public void sing();
    }

    子类Child 集成父类,必须 重写@Override父类的所有方法。

    package com.ann.test;
    
    public class Child implements Person{
    
        @Override
        public String name() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int age() {
            // TODO Auto-generated method stub
            return 0;
        }
    
        @Override
        public void sing() {
            // TODO Auto-generated method stub
            
        }
    
    }

    测试代码: 测试代码中调用了过时的sing()函数,产生警告。使用@SuppressWarnings注解 ,可消除警告。

    package com.ann.test;
    
    public class Test {
        @SuppressWarnings("deprecation")
        public void sing() {
            Person p = new Child();
            p.sing();
        }
    }

    2.常见第三方注解:

    Spring:

    • @Autowired:不用配置文件,可以自动生成Dao文件注入进去
    • @Serice
    • @Repository

    Mybatis:

    • @InsertProvider
    • UpdataProvider
    • @Options

    3.注解分类:

    按照运行机制:

    • 编码注解:只存在源码中
    • 编译时注解:存在于源码与.class中 如@override、@Deprecated、@SuppressWarning
    • 运行时注解:运行时将成员变量自动注入(可能会影响运行逻辑)如Spring中的@AutoWired

    按照来源:

    • JDK注解
    • 第三方注解(Spring等)
    • 自定义注解

    4.自定义注解

    可新建一个Annotation,@interface表示注解。在自定义注解中,

    1. 成员变量必须是无参无异常的形式,可以设置使用default设置默认值
    2. 成员变量的类型:基本数据类型、String、class、Annotation、Enumeration
    3. 成员变量只有一个的时候,一般取名为value();使用的时候,可以直接赋值
    4. 可以没有成员
    package com.ann.test;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ ElementType.METHOD, ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Decription {
    
        String desc();
    
        String author();
    
        int age() default 18;
    }
    @Target:表示注解作用域,关键字包括Constructor(构造函数)、Field(变量)、Local_veriable、method、package、parameter、tyoe(类,接口)
    @Retention:生命周期:source、class、runtime
    @Inherited:可以被子类继承
    @Documented:生成javadoc时包含注解信息

    自定义注解的使用:
    @<注解名>(<成员名1>=<value1>,.......)
    如下:
    package com.ann.test;
    @Decription(desc="I am class description", author = "YM")
    public class Child implements Person{
    
        @Override
        @Decription(desc="I am method description", author = "YM", age = 18)
        public String name() {
            // TODO Auto-generated method stub
            return null;
        }
        @Override
        public int age() {
            // TODO Auto-generated method stub
            return 0;
        }
        @Override
        public void sing() {
            // TODO Auto-generated method stub
            
        } 
    }

    5.解析注解

    1. 首先使用加载器加载类
    2. 找到类上的注解
    3. 拿到注解实例
    4. 找到方法上的注解

    另一种解析方法:以方法上的注解为例

    1. 遍历所有的方法
    2. 拿出所有的注解
    3. 遍历所有注解
    
    
    package com.ann.test;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    public class ParseAnn {
    public static void main(String[] args) {
        try {
            //1.使用类加载器加载类
            Class c=Class.forName("com.ann.test.Child");
            //2找到类上的注解
            boolean isExis = c.isAnnotationPresent(Decription.class);
            if(isExis){
                //3.拿到注解实例
                Decription d=(Decription) c.getAnnotation(Decription.class);
                System.out.println(d.desc());
            }
            //4.找到方法上的注解
            Method[] ms=c.getMethods();
            for(Method m:ms){
                boolean isMExis=m.isAnnotationPresent(Decription.class);
                if(isMExis){
                    Decription mds=(Decription)m.getAnnotation(Decription.class);
                    System.out.println(mds.desc());
                }
            }
            
            //另外一种解析方法
            //1.遍历所有方法
            for(Method m:ms){
                //2拿出所有注解
                Annotation[] an=m.getAnnotations();
                //3遍历所有注解
                for(Annotation a:an){
                    //如果a是我们自定义注解的实例
                    if(a instanceof Decription)
                    {    //将a强转成Decription类
                        Decription d= (Decription)a;
                        System.out.println(d.desc());
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
        
    }
    
    

    输出:

    I am class description
    I am method description
    I am method description

    6.注解实战:

    需求:一张用户表。自动的对每个字段或字段的组合条件进行检索,拼接sql语句,并打印

    Filter.class

    package com.ann.dao;
    
    @Table("user")
    public class Filter {
        @Column("id")
        private int id;
        @Column("userName")
        private String userName;
        @Column("nikeName")
        private String nikeName;
        @Column("age")
        private int age;
        @Column("city")
        private String city;
        @Column("email")
        private String email;
        @Column("mobile")
        private String mobile;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getNikeName() {
            return nikeName;
        }
    
        public void setNikeName(String nikeName) {
            this.nikeName = nikeName;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public String getMobile() {
            return mobile;
        }
    
        public void setMobile(String mobile) {
            this.mobile = mobile;
        }
    }

    Table (自定义注解)作用域为TYPE表示类

    package com.ann.dao;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Table {
        public String value();
    }

    Column (自定义注解)

    package com.ann.dao;
    
    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 Column {
        public String value();
    }

    Test :

    package com.ann.dao;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Test {
        // 1.首先考虑代码怎么与数据库做映射 filter是与数据库关系最紧密的类-转到filter
        // 2需要考虑query方法如何实现
        public static void main(String[] args) {
            Filter f1 = new Filter();
            f1.setId(10);// 查询id为10的用户
            Filter f2 = new Filter();
            f2.setUserName("Tom");// 查询用户名为tom的用户
            f2.setAge(18);
            Filter f3 = new Filter();
            f3.setEmail("123@qq.com,haha@126.com");
            String sql1 = query(f1);
            String sql2 = query(f2);
            String sql3 = query(f3);
            System.out.println("sql1:" + sql1);
            System.out.println("sql2:" + sql2);
            System.out.println("sql3:" + sql3);
            //写一个filter可以应用到不同的表中
            Filter2 filter2= new Filter2();
            filter2.setAmount(10);
            filter2.setId(1);
            filter2.setName("技术");
            System.out.println(query(filter2));
        }
    
        private static String query(Object f) {
            // 首先用一个StringBuilder来存储字符串表示sql语句
            StringBuilder sb = new StringBuilder();
            // 1获取class
            Class c = f.getClass();
            // 2.获取table名
            boolean isCExis = c.isAnnotationPresent(Table.class);
            if (!isCExis) {
                return null;
            }
            Table t = (Table) c.getAnnotation(Table.class);
            String tableName = t.value();
            sb.append("select * from ").append(tableName).append(" where 1=1");
            // 3.遍历所有字段
            Field[] field = c.getDeclaredFields();
            for (Field fi : field) {
                // 4.处理每个字段对应的sql
                // 4.1拿到字段的名字
                boolean isFExis = fi.isAnnotationPresent(Column.class);
                if (!isFExis) {
                    continue;
                }
                Column col = fi.getAnnotation(Column.class);
                String columnName = col.value();
                // 4.2拿到字段的值(反射)
                String fieldName = fi.getName();// 字段名
                // 先拿到get方法的名字
                String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Object fieldValue = null;
                try {
                    Method getMethod = c.getMethod(getMethodName);
                    fieldValue = getMethod.invoke(f);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 4.3拼接
                if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
                    continue;
                }
                sb.append(" and ").append(fieldName);
                if (fieldValue instanceof Integer) {
                    sb.append(" = ").append(fieldValue);
                } else if (fieldValue instanceof String) {
                    if (((String) fieldValue).contains(",")) {// 邮箱格式包含,表示有多种选择
                        String[] string = ((String) fieldValue).split(",");
                        sb.append(" in (");
                        for(String str:string){
                            sb.append("'").append(str).append("'").append(",");
                        }
                        sb.deleteCharAt(sb.length()-1);
                        sb.append(")");
                    } else {
                        sb.append(" = '").append(fieldValue).append("'");
                    }
    
                }
            }
            return sb.toString();
        }
    }
    sql1:select * from user where 1=1 and id = 10
    sql2:select * from user where 1=1 and userName = 'Tom' and age = 18
    sql3:select * from user where 1=1 and email in ('123@qq.com','haha@126.com')


  • 相关阅读:
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(45)-工作流设计-设计步骤
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(44)-工作流设计-设计表单
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(43)-工作流设计-字段分类设计
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(42)-工作流设计-表建立
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(41)-组织架构
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(39)-在线人数统计探讨
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(37)-文章发布系统④-百万级数据和千万级数据简单测试
    .Net 转战 Android 4.4 日常笔记(10)--PullToRefresh下拉刷新使用
  • 原文地址:https://www.cnblogs.com/yumiaomiao/p/8525162.html
Copyright © 2020-2023  润新知