概念:Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法。
###JDK自带注解
@Override
@Deprecated
@Suppvisewarnings
###常见第三方注解
Spring
@Autowired
@Service
@Repository
Mybatis
@InsertProvider
@UpdateProvider
@Options
###注解分类
按照运行机制分
源码注解	-->只在源码中存在
编译时注解 	-->注解在源码和.class文件中
运行时注解
按照来源分
JDK注解
第三方注解
自定义注解
元注解:注解的注解
###自定义注解
####定义自定义注解
```
package com.lgd.anno.define;
import java.lang.annotation.*;
/**
 * 使用 @interface关键字定义注解
 * 成员类型是受限的,和发的类型包括原始类型及
 * String,Class,Annotation,Enumeration
 *
 * 如果注解只有一个成员,
 * 则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)。
 * 
 * 注解类可以没有成员,没有成员的注解称为标识注解
 * Created by liguodong on 2016/1/27.
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desciption {
    String desc(); //成员以无参无异常方式声明
    String author();
    int age() default 18; //可以用default为成员定义默认值
}
```
####元注解

---
@Target 表示注解的一个作用域
ElementType.CONSTRUCTOR 构造方法声明
ElementType.FIELD		字段声明
ElementType.LOCAL_VARIABLE	局部变量声明
ElementType.METHOD		方法声明
ElementType.PACKAGE		包声明
ElementType.PARAMETER	参数声明
ElementType.TYPE		类声明
---
@Retention	生命周期
RetentionPolicy.SOURCE	只在源码显示,编译时会丢弃
RetentionPolicy.CLASS	编译时会记录到class中,运行时忽略
RetentionPolicy.RUNTIME	运行时存在,可以通过反射读取
---
@Inherited	标识性的元注解  标识允许子类注解来继承它, **注解继承只会继承到类,不会继承到里面的方法。**
---
@Documented 生成javadoc时,会包含注解
---
####使用自定义注解
语法:
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值3>,...)
```
package com.lgd.anno.define;
/**
 * Created by liguodong on 2016/1/27.
 */
@Desciption(desc = "I have class double eyeColor.",author = "wintfru",age = 22)
public class EyeColor {
    @Desciption(desc = "I have method double eyeColor.",author = "wintfru",age = 22)
    public String eyeColor(){
        return "red";
    }
}
```
**测试**
```
package com.lgd.anno.define;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
 * Created by liguodong on 2016/1/27.
 */
public class ParseAnnoMain {
    public static void main(String[] args) {
        try {
            //1.使用类加载器加载类
            Class c = Class.forName("com.lgd.anno.define.EyeColor");
            //2.找到类上面的注解
            boolean isExist = c.isAnnotationPresent(Desciption.class);
            if(isExist){
                //3.拿到注解实例
                Desciption d = (Desciption) c.getAnnotation(Desciption.class);
                System.out.println(d.desc()+"<--->"+d.author()+"<--->"+d.age());
                //4.找到方法上的注解
                Method[] ms = c.getMethods();
                for(Method m:ms){
                    boolean isMExist = m.isAnnotationPresent(Desciption.class);
                    if(isMExist){
                        Desciption dm = (Desciption) m.getAnnotation(Desciption.class);
                        System.out.println(dm.desc()+"<--->"+dm.author()+"<--->"+dm.age());
                    }
                }
                //另外一种解析方法
                for(Method m:ms){
                    Annotation[] as = m.getAnnotations();
                    for (Annotation a:as){
                        if(a instanceof Desciption){
                            Desciption dm2 = (Desciption)a;
                            System.out.println(dm2.desc()+"<--->"+dm2.author()+"<--->"+dm2.age());
                        }
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
```
运行结果:
`I have class double eyeColor.<--->wintfru<--->22`
`I have method double eyeColor.<--->wintfru<--->22`
`I have method double eyeColor.<--->wintfru<--->22`
###注解实战
**需求:**
1.有一张用户表,字段包括用户ID,用户名,昵称,年龄,性别,所在城市,邮箱,手机号。
2.方便的对每个字段或字段的组合条件进行检索,并打印出SQL。
3.使用方式简单。
```
package com.lgd.application;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Created by liguodong on 2016/1/27.
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}
```
```
package com.lgd.application;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Created by liguodong on 2016/1/27.
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}
```
```
package com.lgd.application;
/**
 * Created by liguodong on 2016/1/27.
 */
@Table("user")
public class FilterUser {
    @Column("id")
    private int id;
    @Column("username")
    private String username;
    @Column("nickname")
    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;
    }
}
```
```
package com.lgd.application;
/**
 * Created by liguodong on 2016/1/28.
 */
@Table("department")
public class FilterDepartment {
    @Column("id")
    private int id;
    @Column("name")
    private String name;
    @Column("leader")
    private String leader;
    @Column("amount")
    private int amount;
    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 getAmount() {
        return amount;
    }
    public void setAmount(int amount) {
        this.amount = amount;
    }
}
```
```
package com.lgd.application;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Created by liguodong on 2016/1/27.
 */
public class Main {
    //匹配邮箱
    //([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,5})+
    private static String regex = "([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,5})+";
    private static Log log = LogFactory.getLog(Main.class);
    public static void main(String[] args) {
        FilterUser f1 = new FilterUser();
        f1.setId(10); //查询id为10的用户
        FilterUser f2 = new FilterUser();
        f2.setUsername("wintfru");   //查询用户名为wintfru的用户
        f2.setAge(22);
        f2.setEmail("liguodong@163.com");
        //查询邮箱为其中任意一个的用户
        FilterUser f3 = new FilterUser();
        f3.setEmail("liguodong@163.com; 66668888@qq.com; thinkpad@sina.com");
        String sql1 = query(f1);
        String sql2 = query(f2);
        String sql3 = query(f3);
        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);
        FilterDepartment fd1 = new FilterDepartment();
        fd1.setName("项目研发部");
        fd1.setAmount(10);;
        String sql4 = query(fd1);
        System.out.println(sql4);
    }
    public static String query(Object filter){
        StringBuilder sb = new StringBuilder();
        //1.获取到class
        Class c = filter.getClass();
        //2.获取到table的名字
        boolean exists = c.isAnnotationPresent(Table.class);
        if(!exists){
            return null;
        }
        Table table = (Table)c.getAnnotation(Table.class);
        String tableName = table.value(); //表名
        sb.append("select * from ").append(tableName).append(" where 1=1");
        //3.遍历所有的字段
        Field[] fArray = c.getDeclaredFields();
        for (Field field:fArray){
            //4.处理每个字段对应的sql
            //4.1 拿到字段名
            boolean fExists = field.isAnnotationPresent(Column.class);
            if (!fExists){
                continue;
            }
            Column column = field.getAnnotation(Column.class);
            String columnName = column.value(); //字段名 注解上面的值
            log.info("columnName:"+columnName);
            log.info("fieldName:"+field.getName());
            //4.2 拿到字段的值
            String fieldName = field.getName(); //属性值
            String getMethodName = "get" +
                    fieldName.substring(0,1).toUpperCase() +
                    fieldName.substring(1);
            Object fieldValue = null;
            try {
                Method getMethod = c.getMethod(getMethodName);
                //通过反射调用
                fieldValue = getMethod.invoke(filter,null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue ==0)) {
                continue;
            }
            //4.3 拼装sql
            sb.append(" and ").append(fieldName);
            if (fieldValue instanceof String){
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher((String)fieldValue);
                if(!matcher.find()) {
                    sb.append(" = ").append("'").append(fieldValue).append("'");
                }
                else{
                    sb.append(" in ( ");
                    String temp = matcher.group();
                    sb.append("'").append(temp).append("'");
                    while (matcher.find()){
                        temp = matcher.group();
                        sb.append(", ").append("'").append(temp).append("'");
                    }
                    sb.append(" )");
                }
            }else if(fieldValue instanceof Integer){
                sb.append(" = ").append(fieldValue);
            }
        }
        return sb.toString();
    }
}
```
运行结果:
`select * from user where 1=1 and id = 10`
`select * from user where 1=1 and username = 'wintfru' and age = 22 and email in ( 'liguodong@163.com' )`
`select * from user where 1=1 and email in ( 'liguodong@163.com', '66668888@qq.com', 'thinkpad@sina.com' )`
`select * from department where 1=1 and name = '项目研发部' and amount = 10`
**项目源码地址:**
`https://github.com/liguodongIOT/JavaFrames/tree/master/AnnocationProject`