zoukankan      html  css  js  c++  java
  • 【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')


  • 相关阅读:
    4.计算机启动过程的简单介绍 计算机启动流程 计算机BIOS作用 POST 开机自检 计算机启动顺序 分区表 操作系统启动
    3.操作系统简单介绍 操作系统发展历史 批处理分时系统 操作系统是什么 操作系统对文件的抽象 进程 虚拟内存是什么 操作系统作用 操作系统功能
    2.计算机组成-数字逻辑电路 门电路与半加器 异或运算半加器 全加器组成 全加器结构 反馈电路 振荡器 存储 D T 触发器 循环移位 计数器 寄存器 传输门电路 译码器 晶体管 sram rom 微处理 计算机
    1.计算机发展阶段 计算机发展历史 机械式计算机 机电式计算机 电子计算机 逻辑电路与计算机 二极管 电子管 晶体管 硅 门电路 计算机 电磁学计算机二进制
    如何解决svn清理失败 不能更新 cleanup失败 cleanup乱码 更新乱码 svn更新提示清理 清理乱码不能清理 svn故障修复SVN cleanup 陷入死循环 svn cleanup时遇到错误怎么办
    eclipse svn插件卸载 重新安装 Subclipse卸载安装 The project was not built since its build path is incomplete This client is too old to work with the working copy at
    java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
    windows资源管理器多标签打开 windows文件夹多标签浏览 浏览器tab页面一样浏览文件夹 clover win8 win10 报错 无响应问题怎么解决 clover卡死 clover怎么换皮肤
    批处理启动vm虚拟机服务 vm12启动无界面启动vm虚拟机系统 windows上如何操作服务 sc net启动关闭服务
    不能ssh连接ubuntu linux 服务器 secureCRT不能ssh连接服务器 不能远程ssh连接虚拟机的ubuntu linux
  • 原文地址:https://www.cnblogs.com/yumiaomiao/p/8525162.html
Copyright © 2011-2022 走看看