java注解简单讲解及应用

本文深入探讨Java注解的概念,包括内置注解、第三方注解及其应用场景,并介绍如何自定义注解及其实现动态SQL生成的具体案例。
1、java中常见的注解


jdk自带的注解:
                @Override    覆盖父类方法


	        @Override
	        public String name() {
		return null;
	           }

当发现父类的方法定义的有些问题,但是又不能删除,因为有些地方还在
调用这个接口则:


                @Deprecated   表示方法已经过时


父类中设置方法过时:
          	@Deprecated
	        public void sing();

                @Suppvisewarnings  忽视方法过时的警告

当测试类调用时,会出现方法过时的警告,点击感叹号,添加忽视过时:
                @SuppressWarnings("deprecation")
	        public void sing(){
		Person p = new child();
		p.sing();
	                 }



2、常见的第三方注解:


Spring :


                @Autowired

                @Service

                @Repository

Mybatis :
 
                @InterProvider

                @UpdateProvider
          
                @Options
              
  
3、注解的分类:


                -->源码注解
                注解只在源码中存在,编译成.class文件就没了


                -->编译时注解
                注解在源码和.class文件中存在
                例如:@Override告诉编译器覆盖父类方法,然后进行编译


                -->运行时注解
                注解在运行阶段还起作用,影响运行逻辑          
                例如:@Autowired运行时把成员变量装配进来


                元注解:给注解进行的注解




4、自定义注解:


   声明:
      @Target({ElementType.METHOD,ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Inherited
      @Documented
      public @interface Description{// 使用@interface关键字定义注 


                                      解
        String desc();//成员以无参无异常方式声明


        String author();


        int age() default 18;//可以用default为成员指定一个默认值


        }




    元注解:
      //注解作用域(构造方法、局部变量、方法声明、包声明类接口等)
      @Target({ElementType.METHOD,ElementType.TYPE})
      //注解的生命周期(源码、编译时、运行时)
      @Retention(RetentionPolicy.RUNTIME)
      //表示注解允许子类继承
      @Inherited
      //表示生成javadoc时会包含注解
      @Documented



    使用自定义注解:
      @Description(desc="zy",author="boy",age=18)
      public String eyeColor(){
           return "red";
            }
    这样,@Description注解就在eyeColor()方法上使用


5、解析注解:


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


  运行的逻辑.


   	//1、使用类加载器加载类
		 try {
			Class c = Class.forName


("com.ann.test.child");
			//2、找到类上面的注解(判断指定类上是否存


在Description这个注解)
			boolean isExist = c.isAnnotationPresent


(Description.class);
			if(isExist){
				//3、拿到注解实例
				Description d = (Description)


c.getAnnotation(Description.class);
				System.out.println(d.value());
			}
			//4、找到方法上的注解
			  //首先遍历所有的方法
			   Method[] ms = c.getMethods();
			   for (Method m : ms) {
				   //判断是否有注解
				boolean isMExist = 


m.isAnnotationPresent(Description.class);
				if (isMExist) {
					//如果存在则使用注解
					Description md = 


(Description)m.getAnnotation(Description.class);
					System.out.println


(md.value());
				}
				
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		




     注解的继承:


          父类中添加注解,子类中删除原有注解
          此时还是用上面的解析方式对子类进行注解解析

          此时运行不输出任何东西

          原因是:  @Inherited对于接口继承不起作用
          所以要把Person改为类,而不是接口
          child类中改为extends
          运行 --> 打印出类上的注解,而不打印方法上的注解
          所以注解只继承类上的注解,而不继承方法上的注解




6、项目实现:


需求:对象设置好要查询的条件,调用query()后返回对应的sql语句


Filter.java类:(对应了数据库表中各个字段)

   
   package com.zy.test;


@Table("user")
public class Filter {


   @Column("id")	
   private int id;
   
   @Column("user_name")	
   private String userName;
   
   @Column("nick_name")	
   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 nickNameString) {
	this.nickName = nickNameString;
}




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;
}
   
}




Test实现类:(实现配置好查询条件,调用query返回sql)


package com.zy.test;

public class Test {

	public static void main(String[] args) {


		Filter f1 = new Filter();
		f1.setId(10);//查询id为10的用户
		
		Filter f2 = new Filter();
		f2.setUserName("lucy");//模糊查询用户名为lucy的用


户
		
		Filter f3 = new Filter();
		f3.setEmail


("zy@sina.com,zy@163.com,888888@qq.com");//查询邮箱为其中任意一个


的用户
		
		//调用query进行查询
		String sql1 = query(f1);
		String sql2 = query(f2);
		String sql3 = query(f3);
		
		System.out.println(sql1);
		System.out.println(sql2);
		System.out.println(sql3);
		
	
	}
	
	private static String query(Filter f){
		return null;
	}


}





对Filter类进行添加@Table和@Column两个注解之后,接下来对这两个注解
进行定义:(这里定义注解将对象与数据库中的表对应起来)


Table.java:(设置一个参数为表名,作用域为类或接口)
Column.java:(设置一个参数为列名,作用域为参数)
 


package com.zy.test;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {


	String value();
	
}



package com.zy.test;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {


	String value();
	
}


Test.java中query()方法的实现:(注意这里字段值有String和int类型,所以要定义为 Object类型)
   
      
package com.zy.test;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;




public class Test {




	public static void main(String[] args) {


		Filter f1 = new Filter();
		f1.setId(10);//查询id为10的用户
		
		Filter f2 = new Filter();
		f2.setUserName("lucy");//查询用户名为lucy的用户
		f2.setAge(19);
		
		Filter f3 = new Filter();
		f3.setEmail


("zy@sina.com,zy@163.com,888888@qq.com");//查询邮箱为其中任意一个


的用户
		
		//调用query进行查询
		String sql1 = query(f1);
		String sql2 = query(f2);
		String sql3 = query(f3);
		
		System.out.println(sql1);
		System.out.println(sql2);
		System.out.println(sql3);
		
	
	}
	
	private static String query(Filter f){
       
		 StringBuilder sb = new StringBuilder();
	  
		 //1、获取到class
		 Class c = f.getClass();
		 
		 //2.通过注解获取到table的名字
		boolean exists = c.isAnnotationPresent


(Table.class); 
		if (!exists) {
			return null;
		}
		Table t = (Table)c.getAnnotation(Table.class);
		String tableName = t.value();
		sb.append("select * from ").append


(tableName).append(" where 1=1 ");
		 //遍历所有的字段
		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 columnNameString = column.value();
	    	//4.2 拿到字段的值(通过反射取得get方法的名字,然


后通过反射区调用这个方法,就取得字段值)
	    	String filedName = field.getName();
	    	    //把get加上字段名首字母大写


filedName.substring(0, 1).toUpperCase(),把首字母之后的名字内容拼


装上filedName.substring(1),就拼装成get方法
	    	String getMethodName = "get" + 


filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
	    	    //通过反射获取对应方法
	    	Object fieldValue = null;
	    	try {
				Method getMethod = c.getMethod


(getMethodName);
				//反射调用此方法后获得字段值
			    fieldValue = getMethod.invoke(f);
			} catch (Exception e) {
				e.printStackTrace();
			}
	    	//拼装sql
	    	//如果字段值为空或者字段值在int类型时为0 


fieldValue instanceof Integer && (Integer)fieldValue == 0,将不作


处理
	    	if (fieldValue == null || (fieldValue instanceof 


Integer && (Integer)fieldValue == 0)) {
				continue;
			}
	    	sb.append("and ").append(filedName);
	    	if (fieldValue instanceof String) {
	    		//如果是包含三个邮箱的查询,即包含逗号
	    		if (((String) fieldValue).contains(",")) 


{
					String[] value = 


((String) fieldValue).split(","); 
					sb.append("in(");
					for (String v : value) {
						sb.append


("'").append(v).append("'").append(",");
					}
					//把最后一个逗号删掉
					sb.deleteCharAt


(sb.length()-1);
					sb.append(")");
				}else{
					
					sb.append("=").append


("'").append(fieldValue).append("'");
				}
			}
	    	else if (fieldValue instanceof Integer) {
				sb.append("=").append


(fieldValue);
			}
		}
		 
		 return sb.toString();
		 
	}


}


现在如果有第二张表(Department.java),也需要这样的方式进行sql生成
则只需要在对应对象中添加@Table和@Column注解即可


Department.java:


package com.zy.test;


@Table("department")
public class Department {


   @Column("id")	
   private int id;
   
   @Column("name")	
   private String name;
   
   @Column("leader")	
   private String leader;
	
   @Column("number")	
   private int number;


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 getNumber() {
	return number;
}


public void setNumber(int number) {
	this.number = number;
}
   
   
}



只需要把query()方法中参数改为Object,这样就所有对象添加了注解的都有效了


	Department d = new Department();
		d.setId(1);
		d.setLeader("kkk");
		d.setNumber(111);
		System.out.println(query(d));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值