Java注解又称Java标注,通俗的说注解就是对某一事物添加注释说明,是Java 5.0版本开始支持加入源代码的特殊语法元数据。Java语言中的类、方法、变量、参数和包都可以被标注,Java标注可以通过反射获取标注内容。在编译器生成类文件是,标注可以嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。
注解提供了安全的类似注释的机制,用来将任何的信息或元数据与程序元素进行管理。
注解的原理:
注解不会影响程序代码的执行。
@Override
检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated
标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings
指示编译器去忽略注解中声明的警告。
测试,新建一个Person接口,里面定义三个方法,name()个age()用来定义姓名和年龄。
package com.stuspring.annotation;
public interface Person {
public String name();
public int age();
@Deprecated
public void sing();
}
Son类继承Person类:
package com.stuspring.annotation;
public class Son implements Person {
@Override
public String name() {
return null;
}
@Override
public int age() {
return 0;
}
@Override
public void sing() {
}
}
@Override表明该方法是从父类继承而来的。如果在Person类中删除一个sing()方法,Son类的sing()方法仍然使用@Override来标注编译器就会报错,因为父类中并没有这个方法。
在父类中把sing()方法标注为@Deprecated,表明该方法已经过时,不推荐使用了。调用的时候会给出警告:
如果想忽略警告,可以使用@SuppressWarnings标注:
按运行机制分,注解分为:
按照注解来源可以分为:
元注解是对Java注解进行注解。Java 5.0定义的元注解在
import java.lang.annotation
包中,有以下四种类型:
如下两个注解,它们的作用域分别为方法和域。
@Target(ElementType.TYPE)
public @interface Table{
//数据表名称注解,默认值为类名称
public String tableName() default "className";
}
@Target(ElementType.FIELD)
public @interface NoDBColumn{}
自定义注解的语法:
@<注解名>(<成员1>=<成员值1>,<成员1>=<成员值1>)
@Description(desc="I am eyeColor",author="Mooc boy",age=18)
新建一个Description.java,代码如下:
package com.stuspring.annotation;
import java.lang.annotation.*;
/** * Created by bee on 17/4/30. */
@Target({ElementType.METHOD}) //作用域 用在方法上
@Retention(RetentionPolicy.RUNTIME) //声明周期
@Inherited //允许子继承
@Documented //生成javadoc时会包含注解
public @interface Description {
String desc();//成员无参无异常方式声明
String author();
int age() default 18;// 使用default为成员指定一个默认值
}
上面代码中定义了一个注解,注解的名字为Description,里面有desc、author、age三个成员,注解作用在方法上,生命周期为在运行时扔有作用,允许子继承,生成javadoc会包含注解。
通过反射来获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。
首先自定义一个注解,Desc.java
package com.stuspring.annotation;
import java.lang.annotation.*;
/** * Created by bee on 17/5/3. */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Desc {
String value();
}
在Son.java中使用注解:
package com.stuspring.annotation;
/** * Created by bee on 17/4/30. */
@Desc("I am class annotation")
public class Son implements Person {
@Override
@Desc("I am method annotation")
public String name() {
return null;
}
@Override
public int age() {
return 0;
}
@Override
public void sing() {
}
}
通过反射获取注解的信息,ParseAnn.java
package com.stuspring.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/** * Created by bee on 17/5/3. */
public class ParseAnn {
public static void main(String[] args) {
//1.使用类加载器加载类
try {
Class c = Class.forName("com.stuspring.annotation.Son");
//2.找到类上面的注解
boolean isExist = c.isAnnotationPresent(Desc.class);
if (isExist) {
//3.拿到注解实例
Desc desc = (Desc) c.getAnnotation(Desc.class);
//4.打印注解的值
System.out.println(desc.value());
}
//5.找到方法上的注解
Method[] ms = c.getMethods();//得到类上的所有方法
for (Method m : ms) { //遍历
boolean isExistMethod = m.isAnnotationPresent(Desc.class);
if (isExistMethod) {
Desc desc = m.getAnnotation(Desc.class);
System.out.println(desc.value());
}
}
//6.另一种解析方法
for (Method m:ms){
Annotation[] anns=m.getAnnotations();
for (Annotation a:anns){
if (a instanceof Desc){
Desc desc= (Desc) a;
System.out.println(desc.value());
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
I am class annotation
I am method annotation I am method annotation
项目说明:
实现一个持久层框架,用来代替Hibernate的解决方案,核心代码是通过注解来实现。
需求:
1.有一张用户表,包括用户ID、用户名、昵称、年龄、性别、所在城市、邮箱、手机号
2.方便的对每个字段或字段的组合条件进行检索,打印出SQL。
3.使用方式要足够简单
Filter类:
package com.stuspring.annotation.inaction;
/** * Created by bee on 17/5/3. */
@Table("user")
public class Filter {
@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 void setId(int id) {
this.id = id;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public void setAge(int age) {
this.age = age;
}
public void setCity(String city) {
this.city = city;
}
public void setEmail(String email) {
this.email = email;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public int getId() {
return id;
}
public String getUserName() {
return userName;
}
public String getNickName() {
return nickName;
}
public int getAge() {
return age;
}
public String getCity() {
return city;
}
public String getEmail() {
return email;
}
public String getMobile() {
return mobile;
}
}
Table注解
package com.stuspring.annotation.inaction;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** * Created by bee on 17/5/3. */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
Column注解:
package com.stuspring.annotation.inaction;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** * Created by bee on 17/5/3. */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
测试:
package com.stuspring.annotation.inaction;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/** * Created by bee on 17/5/3. */
public class Test {
public static void main(String[] args) {
Filter f1 = new Filter();
f1.setId(10);
Filter f2 = new Filter();
f2.setUserName("lucy");
Filter f3 = new Filter();
f3.setEmail("[email protected],[email protected],[email protected]");
Filter f4 = new Filter();
f4.setEmail("[email protected]");
Filter f5 = new Filter();
f5.setUserName("Tom");
f5.setAge(20);
String sq1 = query(f1);
String sq2 = query(f2);
String sq3 = query(f3);
String sq4 = query(f4);
String sq5 = query(f5);
System.out.println(sq1);
System.out.println(sq2);
System.out.println(sq3);
System.out.println(sq4);
System.out.println(sq5);
}
public static String query(Filter filter) {
StringBuilder sb = new StringBuilder();
//1.获取到Class
Class c = filter.getClass();
//获取到Table的名字
boolean exist = c.isAnnotationPresent(Table.class);
if (!exist) {
return null;
}
Table table = (Table) c.getAnnotation(Table.class);
String tbName = table.value();
sb.append("SELECT * FROM ").append(tbName).append(" WHERE 1=1 ");
//遍历所有字段
Field[] fArray = c.getDeclaredFields();
for (Field field : fArray) {
boolean fExists = field.isAnnotationPresent(Column.class);
if (!fExists) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//拿到字段的值
String fieldName = field.getName();
Object fieldValue = null;
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
Method getMethod = c.getMethod(getMethodName);
fieldValue = getMethod.invoke(filter, null);
} catch (Exception e) {
e.printStackTrace();
}
//拼装SQL
if (fieldValue == null || (fieldValue instanceof Integer && (Integer) fieldValue == 0)) {
continue;
}
if (fieldValue instanceof String) {
if (((String) fieldValue).contains(",")) {
String[] values = ((String) fieldValue).split(",");
sb.append("in(");
for (String v : values) {
sb.append("\'").append(v).append("\'").append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
} else {
fieldValue = "\'" + fieldValue + "\'";
sb.append(" and ").append(fieldName).append(" = ").append(fieldValue);
}
}else{
sb.append(" and ").append(fieldName).append(" = ").append(fieldValue);
}
}
return sb.toString();
}
}
输出:
SELECT * FROM user WHERE 1=1 and id = 10 SELECT * FROM user WHERE 1=1 and userName = 'lucy' SELECT * FROM user WHERE 1=1 in('[email protected]','[email protected]','[email protected]') SELECT * FROM user WHERE 1=1 and email = '[email protected]' SELECT * FROM user WHERE 1=1 and userName = 'Tom' and age = 20