java注解简单讲解及应用
2016-05-27 15:50
507 查看
1、java中常见的注解
jdk自带的注解:
@Override 覆盖父类方法
当发现父类的方法定义的有些问题,但是又不能删除,因为有些地方还在
调用这个接口则:
@Deprecated 表示方法已经过时
父类中设置方法过时:
@Suppvisewarnings 忽视方法过时的警告
当测试类调用时,会出现方法过时的警告,点击感叹号,添加忽视过时:
2、常见的第三方注解:
Spring :
@Autowired
@Service
@Repository
Mybatis :
@InterProvider
@UpdateProvider
@Options
3、注解的分类:
-->源码注解
注解只在源码中存在,编译成.class文件就没了
-->编译时注解
注解在源码和.class文件中存在
例如:@Override告诉编译器覆盖父类方法,然后进行编译
-->运行时注解
注解在运行阶段还起作用,影响运行逻辑
例如:@Autowired运行时把成员变量装配进来
元注解:给注解进行的注解
4、自定义注解:
声明:
元注解:
使用自定义注解:
5、解析注解:
通过反射获取类、函数或成员上的运行时注解信息,从而动态控制程序
运
4000
行的逻辑.
注解的继承:
父类中添加注解,子类中删除原有注解
此时还是用上面的解析方式对子类进行注解解析
此时运行不输出任何东西
原因是: @Inherited对于接口继承不起作用
所以要把Person改为类,而不是接口
child类中改为extends
运行 --> 打印出类上的注解,而不打印方法上的注解
所以注解只继承类上的注解,而不继承方法上的注解
6、项目实现:
需求:对象设置好要查询的条件,调用query()后返回对应的sql语句
Filter.java类:(对应了数据库表中各个字段)
Test实现类:(实现配置好查询条件,调用query返回sql)
对Filter类进行添加@Table和@Column两个注解之后,接下来对这两个注解
进行定义:(这里定义注解将对象与数据库中的表对应起来)
Table.java:(设置一个参数为表名,作用域为类或接口)
Column.java:(设置一个参数为列名,作用域为参数)
Test.java中query()方法的实现:(注意这里字段值有String和int类型,所以要定义为 Object类型)
现在如果有第二张表(Department.java),也需要这样的方式进行sql生成
则只需要在对应对象中添加@Table和@Column注解即可
只需要把query()方法中参数改为Object,这样就所有对象添加了注解的都有效了
jdk自带的注解:
@Override 覆盖父类方法
@Override public String name() { return null; }
当发现父类的方法定义的有些问题,但是又不能删除,因为有些地方还在
调用这个接口则:
@Deprecated 表示方法已经过时
父类中设置方法过时:
@Deprecated public void sing();
@Suppvisewarnings 忽视方法过时的警告
当测试类调用时,会出现方法过时的警告,点击感叹号,添加忽视过时:
@SuppressWarnings("deprecation") public void sing(){ Person p = new child(); p.sing(); }
2、常见的第三方注解:
Spring :
@Autowired
@Service
@Repository
Mybatis :
@InterProvider
@UpdateProvider
@Options
3、注解的分类:
-->源码注解
注解只在源码中存在,编译成.class文件就没了
-->编译时注解
注解在源码和.class文件中存在
例如:@Override告诉编译器覆盖父类方法,然后进行编译
-->运行时注解
注解在运行阶段还起作用,影响运行逻辑
例如:@Autowired运行时把成员变量装配进来
元注解:给注解进行的注解
4、自定义注解:
声明:
@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Description{// 使用@interface关键字定义注 解 String desc();//成员以无参无异常方式声明 String author(); int age() default 18;//可以用default为成员指定一个默认值 }
元注解:
//注解作用域(构造方法、局部变量、方法声明、包声明类接口等) @Target({ElementType.METHOD,ElementType.TYPE}) //注解的生命周期(源码、编译时、运行时) @Retention(RetentionPolicy.RUNTIME) //表示注解允许子类继承 @Inherited //表示生成javadoc时会包含注解 @Documented
使用自定义注解:
@Description(desc="zy",author="boy",age=18) public String eyeColor(){ return "red"; }这样,@Description注解就在eyeColor()方法上使用
5、解析注解:
通过反射获取类、函数或成员上的运行时注解信息,从而动态控制程序
运
4000
行的逻辑.
//1、使用类加载器加载类 try { Class c = Class.forName ("com.ann.test.child"); //2、找到类上面的注解(判断指定类上是否存 在Description这个注解) boolean isExist = c.isAnnotationPresent (Description.class); if(isExist){ //3、拿到注解实例 Description d = (Description) c.getAnnotation(Description.class); System.out.println(d.value()); } //4、找到方法上的注解 //首先遍历所有的方法 Method[] ms = c.getMethods(); for (Method m : ms) { //判断是否有注解 boolean isMExist = m.isAnnotationPresent(Description.class); if (isMExist) { //如果存在则使用注解 Description md = (Description)m.getAnnotation(Description.class); System.out.println (md.value()); } } } catch (ClassNotFoundException e) { e.printStackTrace(); }
注解的继承:
父类中添加注解,子类中删除原有注解
此时还是用上面的解析方式对子类进行注解解析
此时运行不输出任何东西
原因是: @Inherited对于接口继承不起作用
所以要把Person改为类,而不是接口
child类中改为extends
运行 --> 打印出类上的注解,而不打印方法上的注解
所以注解只继承类上的注解,而不继承方法上的注解
6、项目实现:
需求:对象设置好要查询的条件,调用query()后返回对应的sql语句
Filter.java类:(对应了数据库表中各个字段)
package com.zy.test; @Table("user") public class Filter { @Column("id") private int id; @Column("user_name") private String userName; @Column("nick_name") private String nickName; @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 getNickName() { return nickName; } public void setNickName(String nickNameString) { this.nickName = nickNameString; } 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; } }
Test实现类:(实现配置好查询条件,调用query返回sql)
package com.zy.test; public class Test { public static void main(String[] args) { Filter f1 = new Filter(); f1.setId(10);//查询id为10的用户 Filter f2 = new Filter(); f2.setUserName("lucy");//模糊查询用户名为lucy的用 户 Filter f3 = new Filter(); f3.setEmail ("zy@sina.com,zy@163.com,888888@qq.com");//查询邮箱为其中任意一个 的用户 //调用query进行查询 String sql1 = query(f1); String sql2 = query(f2); String sql3 = query(f3); System.out.println(sql1); System.out.println(sql2); System.out.println(sql3); } private static String query(Filter f){ return null; } }
对Filter类进行添加@Table和@Column两个注解之后,接下来对这两个注解
进行定义:(这里定义注解将对象与数据库中的表对应起来)
Table.java:(设置一个参数为表名,作用域为类或接口)
Column.java:(设置一个参数为列名,作用域为参数)
package com.zy.test; 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 { String value(); }
package com.zy.test; 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 { String value(); }
Test.java中query()方法的实现:(注意这里字段值有String和int类型,所以要定义为 Object类型)
package com.zy.test; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Iterator; public class Test { public static void main(String[] args) { Filter f1 = new Filter(); f1.setId(10);//查询id为10的用户 Filter f2 = new Filter(); f2.setUserName("lucy");//查询用户名为lucy的用户 f2.setAge(19); Filter f3 = new Filter(); f3.setEmail ("zy@sina.com,zy@163.com,888888@qq.com");//查询邮箱为其中任意一个 的用户 //调用query进行查询 String sql1 = query(f1); String sql2 = query(f2); String sql3 = query(f3); System.out.println(sql1); System.out.println(sql2); System.out.println(sql3); } private static String query(Filter f){ StringBuilder sb = new StringBuilder(); //1、获取到class Class c = f.getClass(); //2.通过注解获取到table的名字 boolean exists = c.isAnnotationPresent (Table.class); if (!exists) { return null; } Table t = (Table)c.getAnnotation(Table.class); String tableName = t.value(); sb.append("select * from ").append (tableName).append(" where 1=1 "); //遍历所有的字段 Field[] fArray = c.getDeclaredFields(); for (Field field : fArray) { //4.处理每个字段对应的sql //4.1 拿到字段名 boolean fExists = field.isAnnotationPresent (Column.class); if (!fExists) {//如果不是数据库字段 continue; } Column column = (Column)field.getAnnotation (Column.class); String columnNameString = column.value(); //4.2 拿到字段的值(通过反射取得get方法的名字,然 后通过反射区调用这个方法,就取得字段值) String filedName = field.getName(); //把get加上字段名首字母大写 filedName.substring(0, 1).toUpperCase(),把首字母之后的名字内容拼 装上filedName.substring(1),就拼装成get方法 String getMethodName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1); //通过反射获取对应方法 Object fieldValue = null; try { Method getMethod = c.getMethod (getMethodName); //反射调用此方法后获得字段值 fieldValue = getMethod.invoke(f); } catch (Exception e) { e.printStackTrace(); } //拼装sql //如果字段值为空或者字段值在int类型时为0 fieldValue instanceof Integer && (Integer)fieldValue == 0,将不作 处理 if (fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue == 0)) { continue; } sb.append("and ").append(filedName); if (fieldValue instanceof String) { //如果是包含三个邮箱的查询,即包含逗号 if (((String) fieldValue).contains(",")) { String[] value = ((String) fieldValue).split(","); sb.append("in("); for (String v : value) { sb.append ("'").append(v).append("'").append(","); } //把最后一个逗号删掉 sb.deleteCharAt (sb.length()-1); sb.append(")"); }else{ sb.append("=").append ("'").append(fieldValue).append("'"); } } else if (fieldValue instanceof Integer) { sb.append("=").append (fieldValue); } } return sb.toString(); } }
现在如果有第二张表(Department.java),也需要这样的方式进行sql生成
则只需要在对应对象中添加@Table和@Column注解即可
Department.java: package com.zy.test; @Table("department") public class Department { @Column("id") private int id; @Column("name") private String name; @Column("leader") private String leader; @Column("number") private int number; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getLeader() { return leader; } public void setLeader(String leader) { this.leader = leader; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
只需要把query()方法中参数改为Object,这样就所有对象添加了注解的都有效了
Department d = new Department(); d.setId(1); d.setLeader("kkk"); d.setNumber(111); System.out.println(query(d));
相关文章推荐
- Spring Boot 性能优化
- Spring Boot 性能优化
- Spring如何加载XSD文件(org.xml.sax.SAXParseException: Failed to read schema document错误的解决方法)
- Java 生成MyEclipse8.6注册码
- java日期类格式转化的工具类
- java实现基于PKCS5Padding填充方式的AES加解密
- java多线程
- 【JUC】JDK1.8源码分析之ArrayBlockingQueue(三)
- Java的线程池机制
- Java计算器
- 使用Servlet实现java 文件上传
- Eclipse修改背景颜色
- [疯狂Java]集合:EnumSet、各Set性能分析(选择)
- Struts2源码分析(一)
- intellij idea运行java项目
- java--并发包
- StringMVC的pom.xml
- 基于SpringMVC框架项目Demo
- java导出pdf
- [Spring] - Property注入