注解含义
注解是JDK1.5以后才有的新特性,它至关于一种标记,在程序中加入注解就等于为程序打上某种标记,以后又经过类的反射机制
来解析注解。java
JDK1.5以后内部提供的三个注解mysql
@Deprecated #废弃,过期。 @Override #重写、覆盖。 @SuppressWarnings #压缩警告。
示例
sql
@SuppressWarnings("deprecation") public class AnnotationTest { //四、这里称为压缩警告注解,能够在类上也能够放在方法上,由于该方法用了个已通过期的方法.getYear(),因此会发出警告 //加上这个注解代表取消对deprecation的警告,那么该方法里有过期方法也不会发出预警。同时getYear()的那条横线也消失了。 @SuppressWarnings("deprecation") public static void main(String[] args) { //一、这里的.getYear()方法画了一条横线表示此方法已通过时了,里面方法加上了@Deprecated注解 new Date().getYear(); } //二、这里我经过@Deprecated注解自定义一个已通过时不建议使用的方法。 @Deprecated public String getName() { return "小小"; } //三、重写(覆盖)父类Object的toString()方法 @Override public String toString() { return "小小"; } }
注解示意图
数据库
示例
数组
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface AnCode {//使用@interface关键字定义注解 //若是只有一个属性 强烈建议取名为value String value() default ""; }
在自定义注解上面有四个注解,咱们称为元注解
,下面一个一个解释。app
取值(ElementType)有: 一、CONSTRUCTOR: 用于描述构造器 二、FIELD: 用于描述域(字段申明) 三、LOCAL_VARIABLE:用于描述局部变量 四、METHOD: 用于描述方法 五、PACKAGE: 用于描述包 六、PARAMETER: 用于描述参数 七、TYPE: 用于描述类、接口(包括注解类型) 或enum声明 八、TYPE_PARAMETER:输入参数申明(JDK1.8) 九、TYPE_USE: 使用类型(JDK1.8)
取值(RetentionPoicy)有: 一、SOURCE: 在源文件中有效(即源文件保留) 二、CLASS: 在class文件中有效(即class保留) 三、RUNTIME: 注解永久保留,能够被VM加载时加载到内存中
通常框架注解和咱们自定义注解采用的几乎都是RUNTIME
,由于只有这个才能运行时经过反射来获取注解中的数据。框架
概念
: @Inherited阐述了某个被标注的类型是被继承的。若是一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。ide
注意
:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation
解释
: 好比A继承B,B类的上面有一个注解@A带有元注解@Inherited 那么A也能够拥有B父类的这个注解@A,但接口实现是不能够的。同时须要指出@A注解是须要元注解@Retention(RetentionPolicy.RUNTIME)。工具
参考文章:java @Inherited注解的做用测试
概念
:描述其它类型的annotation应该被做为被标注的程序成员的公共API,所以能够被例如javadoc此类的工具文档化。
一、只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型; 二、参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组; 三、若是只有一个参数成员,最好把参数名称设为"value",后加小括号(也能够不加小括号)
目标
实现一个简单的经过注解生成SQL查询语句。
先建立两个注解
@Table表名注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Table { //数据库表名属性 String value() default ""; }
@Column字段名注解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { //数据库表字段名称和实体属性映射 String value() default ""; }
User实体
@Table("t_user") public class User { /** * 用户Id */ @Column("user_id") private Integer userId; /** * 用户年龄 */ @Column("age") private Integer age; public User(Integer userId, Integer age) { this.userId = userId; this.age = age; } //添加get和set方法 }
解析注解类
public class Query { public static String query(Object object) throws Exception{ StringBuilder sql = new StringBuilder(); //1.利用反射获取Class Class c = object.getClass(); //2.获取Table的名字 boolean isExist = c.isAnnotationPresent(Table.class); if (!isExist) { return null; } Table t = (Table) c.getAnnotation(Table.class); //三、获取注解上的value值 String tableName = t.value(); sql.append("select * form ").append(tableName).append(" where 1 = 1 "); //4.遍历全部的属性字段 Field[] fArray = c.getDeclaredFields(); for (Field field : fArray) { //处理每一个字段对应的sql boolean fExist = field.isAnnotationPresent(Column.class); if (!fExist) { continue; } Column column = field.getAnnotation(Column.class); //数据库字段名 String columnName = column.value(); //五、将user_id 变成 userId String[] columns = columnName.split("_"); StringBuilder columnBuilder = new StringBuilder(); for (int i = 0; i < columns.length; i++) { String s = columns[i]; columnBuilder.append(s.substring(0, 1).toUpperCase()).append(s.substring(1)); } //六、活动属性值 String getMethodName = "get" + columnBuilder.toString(); //get方法名 Method getMethod = c.getMethod(getMethodName); Object fieldValue = getMethod.invoke(object);//类字段值 //七、拼装sql sql.append(" and ").append(columnName).append(" = ").append(fieldValue); } return sql.toString(); } }
测试类
public static void main(String[] args) throws Exception { User user = new User(001, 4); String query = Query.query(user); System.out.println("query = " + query); }
运行结果
经过这个小案例实现了经过注解的方式,生成sql语句。
只要本身变优秀了,其余的事情才会跟着好起来(少将20)