这次给大家介绍一下在Java开发过程中 使用自定义注解开发:
主要知识点:
1.反射 主要用于提取注解信息
2.自定义异常 主要是为了自己自定义一个异常信息
3.自定义注解 本次重点 学会如何自定义注解以及如何使用反射提取注解信息运用到实际开发
下图表示在Java中注解的含义以及注解的分类和如何解析注解
**
*
*/
/**
* ClassName:package-info.java
* @author xg.qiu
* @since JDK1.7
* Aug 3, 2015
* 使用自定义注解:
* @Target :用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
* 取值(ElementType)有:
1.ElementType.CONSTRUCTOR:用于描述构造器
2.ElementType.FIELD:用于描述域
3.ElementType.LOCAL_VARIABLE:用于描述局部变量
4.ElementType.METHOD:用于描述方法
5.ElementType.PACKAGE:用于描述包
6.ElementType.PARAMETER:用于描述参数
7.ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention :@Retention定义了该Annotation被保留的时间长短
取值(RetentionPoicy)有:
1.RetentionPolicy.SOURCE:在源文件中有效(即源文件保留)
2.RetentionPolicy.CLASS:在class文件中有效(即class保留)
3.RetentionPolicy.RUNTIME:在运行时有效(即运行时保留)
@Documented:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,
因此可以被例如javadoc此类的工具文档化。
Documented是一个标识注解,没有成员。
@Inherited :元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的
[必须是extend class 而不是implements interface]
*/
package com.demo.ann;
注解语法:
public @interface 注解名{
// 注解变量
// 元数据类型:基本数据类型 String class enum Annotation 以及上述类型数组
// 如果元数据只有一个时 必须声明为value();
}
/**
*
*/
package com.demo.ann.anns;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ClassName:Table.java
* @author xg.qiu
* @since JDK1.7
* Aug 3, 2015
* 自定义注解:表
* 用法:
* @Table("user")
* public class User
*/
@Target( ElementType.TYPE)// 作用域 类或接口
@Retention( RetentionPolicy.RUNTIME)// 有效期为运行时
public @interface Table {
String value();
}
/**
*
*/
package com.demo.ann;
import com.demo.ann.anns.Column;
import com.demo.ann.anns.Table;
/**
* ClassName:User.java
* JAVABean 用户实体类
* @author xg.qiu
* @since JDK1.7 Aug 3, 2015
*/
@Table("TABLE_USER")
public class User {
@Column("USER_ID")
private int userId;
@Column("USER_NAME")
private String userName;
@Column("PASS_WORD")
private String passWord;
@Column("AGE")
private int age;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
*
*/
package com.demo.ann.anns;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ClassName:Column.java
* @author xg.qiu
* @since JDK1.7
* Aug 3, 2015
* 自定义注解:列
* 用法:
* @Column("userId")
* private int userId;
*/
@Target( ElementType.FIELD)//作用于属性
@Retention( RetentionPolicy.RUNTIME)//有效期为运行时
public @interface Column {
String value();
}
/**
*
*/
package com.demo.ann;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.demo.ann.anns.Column;
import com.demo.ann.anns.Table;
import com.demo.ann.exception.AnnException;
/**
解析注解并返回执行的sql语句
* ClassName:Test.java
* @author xg.qiu
* @since JDK1.7
* Aug 3, 2015
* 测试:使用自定义注解完成数据库的查询返回sql语句
* 1.根据id查询
* 2.根据用户名查询
* 3.根据用户名、密码组合查询
*/
public class Test {
public static void main(String[] args) {
User user1 = new User();
user1.setUserId(1);//根据Id查询
User user2 = new User();
user2.setUserName("xiaoqiu");// 根据用户名查询
User user3 = new User();
user3.setUserName("xiaoqiu");
user3.setPassWord("123456");// 根据用户名、密码组合查询
User user4 = new User();
user4.setUserName("xiaoqiu,zasang,lisi");
String sql1 = executeQuery(user1);
String sql2 = executeQuery(user2);
String sql3 = executeQuery(user3);
String sql4 = executeQuery(user4);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
System.out.println(sql4);
}
/**
* @param user 用户对象
*@return String 返回的是拼装好的sql语句
*/
private static String executeQuery(User user) {
StringBuffer sb = new StringBuffer("select * from ");
//1、获取类
Class<? extends User> c = user.getClass();
//2、查找类是否被注解
boolean isExist = c.isAnnotationPresent(Table.class);
if(!isExist){
try {
// 自定义异常
throw new AnnException("the "+ c.getClass().getName() +" class is not used annotation");
} catch (AnnException e) {
e.printStackTrace();
}
}
// 获取Table注解
Table table = (Table) c.getAnnotation(Table.class);
sb.append( table.value() +" where 1= 1");
//3、查找属性是否被注解
Field[] fields = c.getDeclaredFields();
for(Field f : fields){
//3.1、处理每个字段对应的sql
//3.2、拿到字段值
boolean isFExist = f.isAnnotationPresent(Column.class);
if(!isFExist){
try {
throw new AnnException("the " + f.getName() +" field is not used annotation");
} catch (AnnException e) {
e.printStackTrace();
}
}
// 获取列注解
Column column = f.getAnnotation(Column.class);
String columnName = column.value();
//3.2、获取字段
String fieldName = f.getName();
//3.4、.拿到字段值
Object values = null;
String getFieldMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
Method getMethod = c.getDeclaredMethod(getFieldMethodName);
values = getMethod.invoke(user);
//3.5.拼装sql
if( values == null || ( values instanceof Integer && (Integer) values == 0) ){
continue;
}
sb.append(" and ").append(columnName);
if(values instanceof Integer){
sb.append("=").append(values);
}else if(values instanceof String){
if( ((String) values).contains(",")){
String [] valuesIn = ((String) values).split(",");
sb.append(" in('");
for(String s : valuesIn){
sb.append(s).append("'").append(",");
}
sb.deleteCharAt(sb.length() - 1);
sb.append(")");
}else{
sb.append("='").append(values).append("'");
}
}
} catch (Exception e) {
// 打印堆栈信息
e.printStackTrace();
}
}
// 返回拼装好的sql语句
return sb.toString();
}
}
运行效果:
select * from TABLE_USER where 1= 1 and USER_ID=1
select * from TABLE_USER where 1= 1 and USER_NAME='xiaoqiu'
select * from TABLE_USER where 1= 1 and USER_NAME='xiaoqiu' and PASS_WORD='123456'
select * from TABLE_USER where 1= 1 and USER_NAME in('xiaoqiu',zasang',lisi')