动态的为实体字段添加注解/注解属性

可以动态的给实体添加注解,比如:导出表格的时候,根据条件决定是否导出该字段的列等使用

本例子将所有代码都放入工具类中,实际上有些不能实例化到内存中,只能作为一部分代码放在逻辑中,此种代码以再程序中标注;另一部分是可以持久化到内存,使用完工具类之后也可以继续保存注解或者属性;

使用搭配在文末指出

代码如下:

package com.springcloud.utils;

import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtField;
import org.apache.ibatis.javassist.NotFoundException;
import org.apache.ibatis.javassist.bytecode.AnnotationsAttribute;
import org.apache.ibatis.javassist.bytecode.ConstPool;
import org.apache.ibatis.javassist.bytecode.FieldInfo;
import org.apache.ibatis.javassist.bytecode.annotation.Annotation;
import org.apache.ibatis.javassist.bytecode.annotation.MemberValue;
import org.apache.ibatis.javassist.bytecode.annotation.StringMemberValue;

import java.util.Arrays;
import java.util.Set;


public class AddAnnotion {

    /**
     * 功能:动态的给类属性添加注解
     *  用于本来没有注解,直接添加上一行整注解
     * (可以持久化到内存,可作为工具类使用)
     * @param className     类名
     * @param attributeName 类属性
     * @param typeName      注解类型
     */
    public static void addAnnotation(String className, String attributeName, String typeName) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ct = pool.get(className);
            CtField cf = ct.getField(attributeName);
            FieldInfo fieldInfo = cf.getFieldInfo();
            AnnotationsAttribute attribute = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
            ConstPool cp = fieldInfo.getConstPool();
            Annotation annotation = new Annotation(typeName, cp);
            System.out.println("添加注解" + annotation);
            attribute.addAnnotation(annotation);
            System.out.println("添加后的所有注解" + Arrays.toString(attribute.getAnnotations()));
        } catch (NotFoundException e) {
            System.out.println("此类不存在" + e);
        }
    }

    /**
     * 遍历注解所有属性
     *
     * @param className     类名
     * @param attributeName 类属性
     */
    public static void queryAnnotation(String className, String attributeName) {
        System.out.println("====开始遍历注解所有属性=====");
        System.out.println("");
        try {
            ClassPool pool = ClassPool.getDefault();
            //获取实体类
            CtClass ct = pool.get(className);
            //获取属性
            CtField cf = ct.getField(attributeName);
            //获取属性字段信息
            FieldInfo fieldInfo = cf.getFieldInfo();
            //获取属性字段的运行时可见注释
            AnnotationsAttribute attribute = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
            //获取所有注解
            Annotation[] annotations = attribute.getAnnotations();
            int sum = 0;
            //遍历注解
            for (Annotation annotation : annotations) {
                sum++;
                System.out.println("注解" + sum + ":" + annotation.toString());
                //如果没有属性名,就下一个循环
                if (annotation.getMemberNames() == null) {
                    System.out.println("!无属性名跟属性值!");
                    continue;
                }
                //获取注解的所有属性名,跟属性值
                for (String memberName : annotation.getMemberNames()) {
                    MemberValue memberValue = annotation.getMemberValue(memberName);
                    System.out.println("获取到的注解的属性名:" + memberName);
                    System.out.println("获取到的注解的属性值:" + memberValue);
                }
            }
        } catch (NotFoundException e) {
            System.out.println("此类不存在" + e);
        }
    }

    /**
     * 给字段注解添加属性,添加单一注解的属性
     * (不能持久化到内存,只能作为代码一部分使用)
     * @param className     类名
     * @param attributeName 类属性
     * @param name          指定注解名
     * @param key           给注解添加的属性名
     * @param value         给注解添加的属性的值
     */
    public static void editAnnotation(String className, String attributeName, String name, String key, String value) {
        try {
            ClassPool pool = ClassPool.getDefault();
            //获取实体类
            CtClass ct = pool.get(className);
            //获取属性
            CtField cf = ct.getField(attributeName);
            //获取属性字段信息
            FieldInfo fieldInfo = cf.getFieldInfo();
            //获取该字段的常量池
            ConstPool constPool = cf.getFieldInfo().getConstPool();
            //获取属性字段的运行时可见注释
            AnnotationsAttribute attribute = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
            //获取所有注解
            Annotation[] annotations = attribute.getAnnotations();
            for (Annotation annotation : annotations) {
                //如果没有属性名,就下一个循环
                if (annotation.getMemberNames() == null) {
                    continue;
                }
                if (annotation.toString().contains(name)) {
                    System.out.println("添加属性");
                    //给指定的注解添加属性
                    annotation.addMemberValue(key, new StringMemberValue(value, constPool));
                }
            }

            //遍历检查是否添加上注解
            for (Annotation annotation : annotations) {
                Set<String> memberNames = annotation.getMemberNames();
                if (annotation.getMemberNames() == null) {
                    System.out.println("!无属性名跟属性值!");
                    continue;
                }
                for (String memberName : memberNames) {
                    System.out.println("名称:" + memberName + "值:" + annotation.getMemberValue(memberName));
                }
            }
        } catch (Exception e) {
            System.out.println("捕获异常" + e.getMessage());
        }
    }

    /**
     * 获取指定字段的指定注解
     *
     * @param className     类名
     * @param attributeName 类属性
     * @param annotionName  指定注解名
     */
    public static Annotation getAnnotation(String className, String attributeName, String annotionName) {
        Annotation tableField = null;
        try {
            ClassPool pool = ClassPool.getDefault();
            //获取实体类
            CtClass ct = pool.get(className);
            //获取属性
            CtField cf = ct.getField(attributeName);
            //获取属性字段信息
            FieldInfo fieldInfo = cf.getFieldInfo();
            //获取该字段的常量池
            ConstPool constPool = cf.getFieldInfo().getConstPool();
            //获取属性字段的运行时可见注释
            AnnotationsAttribute attribute = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
            //获取该字段所有注解
            Annotation[] annotations = attribute.getAnnotations();
            for (Annotation annotation : annotations) {
                //注解名包含字段,就命中返回
                if (annotation.toString().contains(annotionName)) {
                    tableField = annotation;
                    return tableField;
                }
            }
        } catch (NotFoundException e) {
            System.out.println("捕获异常" + e.getMessage());
        }
        return tableField;
    }

    /**
     * 根据给定的注解体,给其添加属性
     *  (不能持久化到内存,只能作为代码一部分使用)
     * @param className     类名
     * @param attributeName 类属性
     * @param annotation    注解实体
     * @param key           给注解添加的属性
     * @param value         给注解添加的属性的值
     * @return
     */
    public static Annotation editAnnotationBy(String className, String attributeName, Annotation annotation, String key, String value) {
        try {
            ClassPool pool = ClassPool.getDefault();
            //获取实体类
            CtClass ct = pool.get(className);
            //获取属性
            CtField cf = ct.getField(attributeName);
            //获取该字段的常量池
            ConstPool constPool = cf.getFieldInfo().getConstPool();
            //给指定的注解添加属性
            annotation.addMemberValue(key, new StringMemberValue(value, constPool));
            return annotation;
        } catch (Exception e) {
            System.out.println("捕获异常" + e.getMessage());
        }
        return annotation;
    }

    /**
     * 功能:使用生成的注解体 ;动态的给类注解添加属性
     * (可以持久化到内存,可作为工具类使用)
     * @param className     类名
     * @param attributeName 类属性
     */
    public static void addAnnotationBy(String className, String attributeName, Annotation annotation) {
        try {
            ClassPool pool = ClassPool.getDefault();
            CtClass ct = pool.get(className);
            CtField cf = ct.getField(attributeName);
            FieldInfo fieldInfo = cf.getFieldInfo();
            AnnotationsAttribute attribute = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag);
            attribute.addAnnotation(annotation);
            System.out.println("添加后的所有注解" + Arrays.toString(attribute.getAnnotations()));
        } catch (NotFoundException e) {
            System.out.println("此类不存在" + e);
        }
    }
}

工具类使用举例:
实体

/**
 * @author byChen
 * @date 2021/10/20
 */
public class Animal {
    @TableField(exist = false)
    public String age;
}

工具类:

    @GetMapping("/annotion")
    public R annotion() {
        Annotation tableField = AddAnnotion.getAnnotation("com.springcloud.domain.Animal", "age","TableField");
        System.out.println("添加之前的:"+tableField);
        Annotation annotation = AddAnnotion.editAnnotationBy("com.springcloud.domain.Animal", "age", tableField, "value", "123");
        System.out.println("添加过后的:"+annotation);
        AddAnnotion.addAnnotationBy("com.springcloud.domain.Animal", "age",annotation);
        AddAnnotion.queryAnnotation("com.springcloud.domain.Animal","age");
        return R.ok();
    }
}

运行结果:
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值