在Java程序中通过注解,可以让编程更加简洁、代码更加清晰。因此在Java框架代码中,嵌入了大量的注解。
讲注解,首先得讲注解的概念:Java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法。
一、注解的分类
1、按照运行机制分为源码注解、编译注解和运行时注解
(1)源码注解:注解只在源码中存在,编译成.class文件就不存在了
(2)编译注解:注解在源码和.class文件中都存在,如JDK的三个注解
(3)运行时注解:在运行阶段还起作用,甚至影响运行逻辑的注解,如Spring中的@Autowired注解
2、按照来源分为JDK注解、第三方的注解、元注解和自定义注解
(1)JDK自带注解
@Override:子类中的方法覆盖了父类中的方法时,在方法的前面会出现这个关键字;
@Deprecated:表示一个方法过时了,但仍然可以使用,即在调用加该注解的方法前加上@Suppvisewarning("deprecation")即可;
@Suppvisewarning:结合@Depricated理解;
(2)第三方的注解
如Spring中的@Autowired、@Service和@Repository等;
如Mybatis中的@InsertProvider、@UpdateProvider和@Options等;
(3)元注解:注解的注解称为元注解
(4)自定义注解---本节主要讲解
二、自定义注解
1、自定义注解语法要求:
@Target({ElementType.METHOD, //方法声明
ElementType.TYPE, //类、接口
ElementType.FIELD, //字段声明
ElementType.CONSTRUCTOR, //构造方法声明
ElementType.LOCAL_VARIABLE, //局部变量
ElementType.PACKAGE, //包声明
ElementType.PARAMETER}) //参数声明
@Retention(RetentionPolicy.RUNTIME) //生命周期,有SOURCE(源码)、CLASS(编译)、RUNTIME(运行时)
@Inherited //允许子类继承
@Documented //生成JavaDoc的时候包含的信息
public @interface Description{ //@interface定义注解
String desc(); //方法以无参数、无异常的方式声明
String author();
int age() default 20; //使用default为其指定默认值
}
(1)同时注意成员的类型是受限制的,合法的类型:基本类型、String、Class、Annotation、Enumeration。
(2)如果注解只有一个成员时,成员名必须取名为value(),在使用时可以忽略成员名和复制号(=);
(3)如果注解类没有成员,则称之为标识注解;
2、注解的使用
@<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,……)
@Description(desc="Hello", author="Jack", age=18)
public String Demo(){
return "test";
}
三、自定义注解操作数据库
数据库中的表如图所示:
第一步:建立与数据库中表对应的实体类,并分别在类和方法上插入自定义的注解
类上的注解
方法上的注解
第二步:写测试函数
public class Main {
public static void main(String[] args){
Student stu1 = new Student();
stu1.setSno(20110002);//按sno查询学生
Student stu2 = new Student();
stu2.setMajor("IS");//按专业查询学生
stu2.setName("lisi");
Student stu3 = new Student();
stu3.setName("AAA,HHH,zhangsan,lisi");//按名字查询其中任意一个学生
String sql1 = query(stu1);
String sql2 = query(stu2);
String sql3 = query(stu3);
System.out.println(sql1);
exeQuery(sql1);
System.out.println(sql2);
exeQuery(sql2);
System.out.println(sql3);
exeQuery(sql3);
}
private static String query(Object stu) {
StringBuilder sb = new StringBuilder();
//解析注解:
//1、获取到class
Class clazz = stu.getClass();
//2、获取到table的名字
boolean exists = clazz.isAnnotationPresent(Table.class);
if(!exists)
return null;
Table table = (Table) clazz.getAnnotation(Table.class);
String tableName = table.value();
sb.append("select * from ").append(tableName).append(" where 1=1");
//3、遍历所有字段
Field[] fArray = clazz.getDeclaredFields();
for(Field field : fArray) {
//4、处理每个字段对应的sql
//4.1拿到字段名
boolean fieldExist = field.isAnnotationPresent(Column.class);
if (!fieldExist){
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//4.2拿到字段名
String filename = field.getName();
String getMethodName = "get" + filename.substring(0,1).toUpperCase() + filename.substring(1);
Object filevalue = null;
try {
Method getMethod = clazz.getMethod(getMethodName);
filevalue = getMethod.invoke(stu, null);
} catch (Exception e) {
e.printStackTrace();
}
//4.3拼装sql
if(filevalue == null || ((filevalue instanceof Integer) && ((Integer)filevalue==0)))
continue;
sb.append(" and ").append(filename);
if(filevalue instanceof String) {
if(((String)filevalue).contains(",")){
String[] values = ((String) filevalue).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(filevalue).append("'");
}
}else if(filevalue instanceof Integer)
sb.append(" = ").append(filevalue);
}
return sb.toString();
}
private static void exeQuery(String sql){
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/learn?useUnicode=true&characterEncoding=utf-8&&useSSL=false&serverTimezone=UTC","root", "admin");
PreparedStatement statement = conn.prepareStatement(sql);
ResultSet rs = statement.executeQuery();
while(rs.next()){
System.out.println(rs.getString("sno") + "\t" + rs.getString("name") + "\t" + rs.getString("major"));
}
statement.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
运行测试程序得到如下结果: