【Java进阶】Java注解的使用

Java注解

 

概念:Java提供了一种原程序中的元素关联的任何信息和任何元数据的途经和方法。

 

Java中常见的注解

JDK自带注解

@Override 覆盖父类的方法

@Deprecated 表示这个方法已经过时了

//这个方法已经过时了

@Deprecated

public void sing();

@Suppvisewarnings

//忽略过时的警告

         @SuppressWarnings("deprecation")

         public void test(){

                   Person p = new Child();

                   p.sing();

         }

常见第三方注解

Spring

@Autowired

@Service

@Repository

常见第三方注解

Mybatis

@InsertProvider

@UpdateProvider

@Options

实现接口类不会自动添加@Override 注解,解决方法:

右键项目-> Java Compiler –> Compiler compliance level –> 1.7

 

Java注解的分类

按照运行机制分

源码注解:注解只在源码中存在,编译成class文件就没有了。

编译时注解:注解在源码和.class 文件中都存在。如: @Override

@Deprecated  @Suppvisewarnings

运行时注解: 在运行阶段还起作用,甚至会影响运行逻辑的注解。 如@Autowired

按照来源划分

来自JDK的注解

来自第三方的注解

我们自己定义的注解

元注解

注解的注解

 

自定义注解的语法要求

/*
 * 下面四个注解为元注解
 * @Target标识注解的作用域:可配置的值为
 * CONSTRUCTOR(构造方法声明)FIELD(字段声明)LOCAL_VARIABLE(局部变量声明)
 * METHOD(方法声明) PACKAGE(包声明) PARAMETER(参数声明) TYPE(类,接口)
 * @Retention 注解的生命周期,可选的值有 
 * SOURCE(只在源码显示,编译时会丢弃)
 * CLASS(编译时会记录到class中,运行时忽略)
 * RUNTIME(运行时存在,可以通过反射读取)
 * @Inherited 允许子类继承,继承时只会继承类上面的注解
 * @Documented 生成javadoc时会包含注解的信息
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
/*使用@interface 关键字定义注解*/
public @interface Description{
	/*
	 *1.成员的类型是受限的,合法的类型包括原始类型及String,Class
	 *Annotation,Enumeration 
	 *2.如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略
	 *成员名和赋值号(=)
	 *3.注解类可以没有成员,没有成员的注解称为标识注解
	 */
	String desc();//成员以无参无异常方式声明
	
	String author();
	
	int age() default 18; //可以用default为成员指定一个默认值
}
//如何使用注解
class UseAnn{
	@Description(desc="I am eyeColor",author="meng",age=24)
	public String eyeColor(){
		return "red";
	}
}

解析注解

 

通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。

在Child类上加上注解

@Description(desc="I am a class annotation")
public class Child implements Person{
	@Description(desc="I am a method annotation")
	@Override
	public String name() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public int age() {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public void sing() {
		// TODO Auto-generated method stub
	}
}


解析Child类的注解,通过反射

public class ParseAnn {
	public static void main(String[] args) {
		//1. 使用类加载器加载类
		try{
			Class c = Class.forName("com.ann.test.Child");
			//2. 找到类上面的注解
			boolean isExist = c.isAnnotationPresent(Description.class);
			if(isExist){
				//3. 拿到注解实例
				Description d = (Description)c.getAnnotation(Description.class);
				System.out.println(d.desc());
			}
			
			//4.找到方法上的注解
			Method[] ms = c.getMethods();
			for(Method method : ms){
				boolean isMExist = method.isAnnotationPresent(Description.class);
				if(isMExist){
					Description d = (Description)method.getAnnotation(Description.class);
					System.out.println(d.desc());
				}
			}
			
			//另一种解析方法
			for(Method m : ms){
				//获取所有的注解
				Annotation[] as = m.getAnnotations();
				for(Annotation a : as){
					if(a instanceof Description){
						Description d = (Description) a;
						System.out.println(d.desc());
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

注解实战

 

需求:

1.      有一张用户表,字段包括用户ID,用户名,昵称,年龄,性别,所在城市,邮箱,手机号。

2.      方便对每个字段或字段的组合条件进行检索,并打印出SQL。

3.      使用方式要足够简单。

 

首先创建Filter.java类,指定和数据库对应的字段。并加上注释
@Table("user")
public class Filter {
	@Column("id")
	private int id;
	@Column("usrName")
	private String usrName;
	@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 getUsrName() {
		return usrName;
	}
	public void setUsrName(String usrName) {
		this.usrName = usrName;
	}
	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;
	}
}
创建表注解 Table.java
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
	//只有一个方法,则名字用value,这是一个约定
	String value();
}
创建字段注解 Column.java

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
	String value();
}
使用注解拼接SQL语句 Test.java

public class Test {
	public static void main(String[] args) {
		Filter f1 = new Filter();
		f1.setId(10);//查询id为10 的用户
		
		Filter f2 = new Filter();
		f2.setUsrName("lucy");//查询用户名为lucy的用户
		
		Filter f3 = new Filter();
		f3.setEmail("liu@sina.com,zh@163.com,aa@qq.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);
		
		/**
		 * 假如这里有了一个Filter2 类,描述了另一个表的内容,我们这里还是可以直接使用
		 */
		Filter2 f4  = new Filter2();
		f4.setLeader("Dancy");
		f4.setId(12);
		String sql4 = query(f4);
		System.out.println(sql4);
	}
	private static String query(Object f){
		StringBuilder sb = new StringBuilder();
		//1.获取到Class
		Class c = f.getClass();
		//2.获取到table的名字
		boolean isExist = c.isAnnotationPresent(Table.class);
		if(!isExist){
			return null;
		}
		Table t = (Table) c.getAnnotation(Table.class);
		String tableName = t.value();
                // where 1=1 为拼接的技巧
		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 = (Column) field.getAnnotation(Column.class);
			String columnName = column.value();
			
			//4.2 拿到字段的值
			String filedName = field.getName();
			//拼接出get方法的名字
			String getMehodName = "get"+filedName.substring(0,1).toUpperCase()+filedName.substring(1);
			Object filedValue = null;
			try {
				//根据方法名字用反射获取方法对象
				Method getMethod = c.getMethod(getMehodName);
				filedValue = getMethod.invoke(f, null);
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			//4.3拼装sql
			if(filedValue == null ||
					(filedValue instanceof Integer && (Integer)filedValue == 0)){
				continue;
			}
			sb.append(" and ").append(filedName);
			//如果是String类型的sql语句需要拼接上单引号
			if(filedValue instanceof String){
				//如果字符串中包含逗号,则说明是email
				if(((String)filedValue).contains(",")){
					String[] values = ((String)filedValue).split(",");
					sb.append(" in(");
					for(String v : values){
						sb.append("'").append(v).append("'").append(",");
					}
					//删掉最后一个逗号
					sb.deleteCharAt(sb.length()-1);
					sb.append(")");
				}else{
					sb.append(" = ").append("'"+filedValue+"'");
				}
			}else if(filedValue instanceof Integer){
				sb.append(" = ").append(filedValue);
			}	
		}
		return sb.toString();
	}
}

SQL拼接结果,我们还可以实现更复杂的SQL拼接

上例 代码下载





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值