java中注解和反射的运用

注解(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);
 
    }
}

结语:保持每天进步的自己,去迎接未来的每一天,与君共勉

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值