一、解释注解
Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。从某些方面看,annotation就像修饰符一样被使用,并应用于包、类 型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在Annotation的“name=value”结构对中。
Annotation的成员在Annotation类型中以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。在此有一个特定的默认语法:允许声明任何Annotation成员的默认值:一个Annotation可以将name=value对作为没有定义默认值的Annotation成员的值,当然也可以使用name=value对来覆盖其它成员默认值。这一点有些近似类的继承特性,父类的构造函数可以作为子类的默认构造函数,但是也可以被子类覆盖。
Annotation能被用来为某个程序元素(类、方法、成员变量等)关联任何的信息。需要注意的是,这里存在着一个基本的规则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。另外,尽管一些annotation通过java的反射api方法在运行时被访问,而java语言解释器在工作时忽略了这些annotation。正是由于java虚拟机忽略了Annotation,导致了annotation类型在代码中是“不起作用”的; 只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。本文中将涵盖标准的Annotation和meta-annotation类型,陪伴这些annotation类型的工具是java编译器(当然要以某种特殊的方式处理它们)。
二、注解分类
(1)、按照运行机制分为
源码注解:注解只在源码中存在,编译成class就没有了
编译时注解:注解在源码和.class文件中都存在(如:JDK内置系统注解)
运行时注解:注解在运行还起作用,甚至会影响运行逻辑的注解(如:Spring中@Autowried)
(2)、按照来源
JDK内置系统注解
@Override 用于修饰此方法覆盖了父类的方法;
@Deprecated 用于修饰已经过时的方法;
@suppressWarings("deprecation") 用于通知java编译器忽略特定的编译警告。
元注解
@Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD})
// Target 注解的作用域 CONSTRUCTOR 构造方法声明,FIELD 字段声明,LOCAL_VARIABLE 局部变量声明 ,METHOD 方法声明,PACKAGE 包声明,PARAMETER 参数声明,TYPE 类接口。
@Retention(RetentionPolicy.RUNTIME)
//Retention 生命周期 SOURCE 只在源码显示,编译时会丢弃,CLASS 编译时会记录到class中,运行时忽略,RUNTIME 运行时存在,可以通过反射读取。
@Inherited
//Inherited 允许子类继承
@Documented
//Documented 生成javadoc的时候包含注解
自定义注解
1.成员类型是受限的,合法的类型包括原始类型及String,Calss,Anootation,Enumreation
2.如果注解已有一个成员,则成员名必须取名为Vaue(),在使用的时可以忽略成员名和赋值号(=)
3.注解类可以没有成员,没有成员的注解称为标识注解
public @interface Description{//使用@interface关键字注解
String name();//成员以无参无异常方式声明
String author();
int age() default 19;//可以用default为成员变量指定一个默认值
}
第三方注解
springmvc mabatis 等框架的注解
三、例子
功能: 定义一个java 实体类user,通过注解和数据库一张表对应
并且生成sql语句
1、定义Table注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
2、定义数据库列名注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
3、定义User实体类 和 数据库表对应
@Table("t_user")
public class User {
@Column("user_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 nickname) {
this.nickname = nickname;
}
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;
}
}
4、测试类
public class Test {
public static void main(String[] args) {
User user1 = new User();
user1.setId(0001);//查询ID为0001的用户
user1.setNickname("繁华");//查询昵称为繁华的用户
User user2 = new User();
user2.setUsername("Jack");//查询用户名为Jack的用户
user2.setAge(18);//查询年龄为18的用户
User user3 = new User();
user3.setEmail("lian@sina.com,jiang@qq.com");//查询邮箱为其中任意一个的用户
String sql1 = query(user1);
String sql2 = query(user2);
String sql3 = query(user3);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
}
private static String query(User user){
StringBuilder sb = new StringBuilder();
//1.获取到Class
Class< ?> class1 = user.getClass();
//2.获取到table的名字
boolean flag1 = class1.isAnnotationPresent(Table.class);
if(!flag1){
return null;
}
Table table = (Table)class1.getAnnotation(Table.class);
String tableName = table.value();
sb.append("select * from ").append(tableName).append(" where 1=1");
//3.遍历所有的字段
Field[] fields = class1.getDeclaredFields();
for (Field field : fields) {
//4.处理每个字段对应的sql
//拿到字段名
boolean flag2 = field.isAnnotationPresent(Column.class);
if (!flag2) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//拿到字段值
String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Object fieldValue = null;
try {
Method getMethod = class1.getMethod(getMethodName);
fieldValue = getMethod.invoke(user);
} catch (Exception e) {
e.printStackTrace();
}
//拼装sql
if(fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue == 0)){
continue;
}
sb.append(" and ").append(columnName);
if(fieldValue instanceof String){
if(((String)fieldValue).contains(",")){
String[] values = ((String)fieldValue).split(",");
sb.append(" in(");
for (String value : values) {
sb.append("'").append(value).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();
}
}
select * from t_user where 1=1 and user_id = 1 and nick_name = '繁华'
select * from t_user where 1=1 and user_name = 'Jack' and age = 18
select * from t_user where 1=1 and email in('lian@sina.com','jiang@qq.com')
参考博文:https://blog.youkuaiyun.com/c1481118216/article/details/52911263
https://blog.youkuaiyun.com/Ssunsets/article/details/51042494