注解(annonation)在java5中进行引入的辅助工具库,它的核心作用是在类,方法,变量,参数,包进行标注,结合反射以此在程序运行时对标注的对象行为做自定义逻辑的处理。
Java中的注解由内置注解和元注解组成。
元注解介绍:
创建注解:public @interface Knowledge {}
//@Target 注解的用用范围如下:
//TYPE:表示可以用来修饰类、接口、注解类型或枚举类型PACKAGE:可以用来修饰包
//PARAMETER:可以用来修饰参数;
//ANNOTATIONTYPE:可以用来修饰注解类型
//METHOD:可以用来修饰方法
//FIELD:可以用来修饰属性 (包括枚举常量);
//CONSTRUCTOR:可以用来修饰构造器;
//LOCALVARIABLE:可用来修饰局部变量
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) //定义注解的生命周期
@Inherited //子类是否可以继承此注解
@Documented //文档注解,会被javadoc工具文档化
注解本身不具有任何含义如何让注解具有一定的含义呢,那就需要结合java的反射功能进行使用。
反射:在程序运行状态中,对任何类以及对象的所有的属性以及方法,都能进行动态的进行信息的获取以及对象方法的调用,这种功能成为java的反射的功能
反射的优缺点:
1:反射可以针对已经装载到JVM的类的信息,类的方法,类的属性都可以进行访问
2:反射提高程序的扩展性,灵活性,降低耦合性,提高自适应能力
3:反射会对程序的性能产生影响,(影响的时间单位在毫秒级)同时代码的可读性变低
反射常用的API
此时有幸看到这里的你,也许会有一丝的疲倦和枯草乏味,但是有一句歌唱的好,要想练就绝世武功就要忍受常人难忍受的痛(歌词源于:下山)与君共勉
API案例编写
@Slf4j public class Reflection { public static void main(String[] args) throws Exception { //方式1:通过反射获取类名,包名 Common common = new Common(); Class<? extends Common> acls = common.getClass(); //通过反射获取类的元信息 //方式2:通过反射获取类名,包名 Class<?> acls1 = Class.forName("com.java.base.exercise.annonation.Common"); //通过反射获取类的元信息 log.info("获取类名+包名:::::"+acls); log.info("获取类名+包名:::::"+acls1); log.info("获取类名:::::"+acls1.getSimpleName()); //通过反射获取类得属性 Field[] fields = acls.getDeclaredFields(); for (Field field : fields) { log.info("类得属性:::"+field); } //通过反射获取类属性对应得值 common.setName("不良帅"); common.setAddress("大唐盛世"); for (Field field : fields) { field.setAccessible(true); //设置属性得可见性, 对属性的获取和赋值都需要进行设置可见性 log.info("类得属性:::"+field.get(common)); } //通过反射进行实例化对象,对对象的属性值进行赋值 Object common1 = acls.newInstance(); for (Field field : fields) { field.setAccessible(true); if(field.getName().equals("name")){ field.set(common1,"反射实例化赋值::不良帅"); }else { field.set(common1,"反射实例化赋值::大唐盛世"); } } log.info(common1.toString()); //通过反射获取类中的方法 Method[] methods = Common.class.getDeclaredMethods(); for (Method method : methods) { if(method.getName().equals("getRich")){ method.setAccessible(true); log.info("反射获取类中的方法:::"+method.getName()); } } //通过反射调用私有修饰的方法进行执行 Method method = acls.getDeclaredMethod("getRich"); method.setAccessible(true); Object invoke = method.invoke(common); log.info("通过反射调用私有修饰的方法,执行的Result"+invoke); //反射结合注解得运用 //1:获取类上得注解 Knowledge annotation = acls.getAnnotation(Knowledge.class); String name = annotation.name(); String[] meters = annotation.meters(); for (String meter :meters) { log.info("获取类上得注解得内容"+meter); } log.info("获取类上得注解得内容:::"+name); //2: 获取类中方法上得注解 for (Method method1 : methods) { Knowledge annotation1 = method1.getAnnotation(Knowledge.class); if(Objects.isNull(annotation1)) continue; String name1 = annotation1.name(); String[] meters1 = annotation1.meters(); for (String s : meters1) { log.info("获取类中方法上得注解的内容:::: meters1 "+s); } log.info("获取类中方法上得注解的内容 :::::"+name1); } //3: 获取类中属性上得注解 for (Field field : fields) { Knowledge fieldAnnotation = field.getAnnotation(Knowledge.class); if(Objects.isNull(fieldAnnotation)) continue; String name1 = fieldAnnotation.name(); String[] meters1 = fieldAnnotation.meters(); for (String s : meters1) { log.info("获取类中属性上得注解的内容:::: meters1 "+s); } log.info("获取类中属性上得注解的内容 :::::"+name1); }
反射结合注解模拟需求案例编写
1:需求:
将实体类的类注解解析出作为表名,
实体类的属性如有注解标注则作为查询字段(如果注解没有设置值内容,则实体属性命名和和表字段保持一致)
属性有注解标注,同时属性又被赋值则为查询条件
形成的sql案例如下:
Select 字段名 from 表名 where 字段名=属性赋值的值
实现的核心逻辑如下:
public class GenerntUtil { //Select 字段名 from 表名 where 字段名=属性赋值的值 public String queryData(Object tab) throws IllegalAccessException { StringBuffer sb = new StringBuffer(); StringBuffer sb2 = new StringBuffer(); sb.append(" select "); //解析实体类的类注解,获取表名 Class<?> aClass = tab.getClass(); TableName tabAnnation = aClass.getAnnotation(TableName.class); if(Objects.isNull(tabAnnation)){ throw new RuntimeException("table name is not exist !!!!!"); } String tableName = tabAnnation.name(); //解析实体类的属性,是否被注解标注, // 实体类的属性如有注解标注则作为查询字段(如果注解没有设置值内容, // 则实体属性命名和和表字段保持一致) Field[] fields = aClass.getDeclaredFields(); for (Field field : fields) { Clounm clounm = field.getAnnotation(Clounm.class); if(Objects.isNull(clounm)) continue; if(clounm.value().equals("")){ //表名字段和实体类字段一致 String name = field.getName(); field.setAccessible(true); Object o = field.get(tab); if(o!=null&&Integer.parseInt(o.toString())!=0){ //实体字段被赋值,需要作为查询条件 sb2.append(" where "+name+"="+o); sb.append(" "+name+" , "); } }else { //作为条件查询的字段,解析注解的内容 String clname=clounm.value(); sb.append(" "+clname+" , "); field.setAccessible(true); Object o = field.get(tab); if(o!=null&&Integer.parseInt(o.toString())!=0){ //实体字段被赋值,需要作为查询条件 sb2.append(" where "+clname+"="+o); } } } sb.append("from"+" "+tableName); sb.append(sb2.toString()); return sb.toString(); } public static void main(String[] args) throws IllegalAccessException { GenerntUtil generntUtil = new GenerntUtil(); Order order = new Order(); order.setUserNo("146987008"); String result= generntUtil.queryData(order);
System.out.println(result);
} }
结语:保持每天进步的自己,去迎接未来的每一天,与君共勉