自定义注解,根据反射拿到被注解修饰的类,方法,属性

自定义注解,根据反射拿到被注解修饰的类,方法,属性

自定义注解

//作用在类,类的成员变量上 ElementType.TYPE该注解作用于类
//ElementType.FIELD 该注解作用于类的属性
//ElementType.METHOD 该注解作用于方法
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//生命周期 
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AnnotNote {

    String value() default "0";
    int age() default 0;

}

在方法上加上

@Bean
@AnnotNote
public Student anStu(){
        return new Student("张",12,"男");
}

在属性上加上

package com.lqy.redis.bean;

/**
 * @title: DataBean
 * @Author Tan
 * @Date: 2020/8/5 11:55
 * @Version 1.0
 */
/**
 * C
 * FileName: DataBean
 * Author:  
 * Date:     2020/6/17 16:02
 * Description:
 * History:
 * <author>       <version>         <desc>
 * zhaoyi         1.0               描述
 */

import lombok.Data;
import lombok.ToString;

/**
 * 〈功能简述〉<br>
 * 〈数据实体〉
 *
 * @author 35903
 * @create 2020/6/17
 * @since 1.0
 */
@Data
@ToString
public class DataBean {


    /**
     * 数据值
     */
    @AnnotNote()
    private double dataValue;

    /**
     * 数据值时间
     */
    @AnnotNote()
    private String dataValueTime;

    /**
     * 入库时间
     */
    String insertTime;
    /**
     * 相应的数据点号
     */
    private String dataId;
    /**
     * 时间间隔(5分钟,15分钟...)
     */
    private int dataInterval;


}

测试


@Autowired
    PublicReflectionUtils publicReflectionUtils;
@Autowired
ApplicationContext ac;

 ApplicationContext applicationContext = SpringApplicationContextUtil.getApplicationContext();
        String[] beanNamesForType = ac.getBeanNamesForType(Student.class);

        Class<DruidConfig> druidConfigClass = DruidConfig.class;
        Method[] methods = druidConfigClass.getMethods();

//拿到被注解修饰的方法Bean
        for (Method name:methods
             ) {
            if(name.isAnnotationPresent(AnnotNote.class)){
                String name1 = name.getName();
                Object b = ac.getBean(name1);
                System.out.println("拿到Bean"+b);
                System.out.println("被修饰的方法"+name1);
            }
        }
        //模拟传入的对象
        DataBean dataBean = new DataBean();
        dataBean.setDataValue(15);
        dataBean.setInsertTime("adsd");
        dataBean.setDataValueTime("sad");
        dataBean.setDataId("454");
        //根据反射拿到这个类
        Class<? extends DataBean> aClass = dataBean.getClass();
        //拿到这个类中所有属性
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field:declaredFields
             ) {
            //判断属性上是否加了AnnotNote这个注解
            if(field.isAnnotationPresent(AnnotNote.class)){
                String s = field.getName().toString();
                //通过反射根据这个属性名,跟类,拿到这个类中这个属性的值
                Object fieldValueByName = publicReflectionUtils.getFieldValueByName(s, dataBean);
                System.out.println(s+"属性的值:"+fieldValueByName);
                //拿到属性上被这个注解修饰的注解值
                AnnotNote annotation = field.getAnnotation(AnnotNote.class);
                System.out.println("annotation:"+annotation.value());
                //属性描述器
                PropertyDescriptor ps = new PropertyDescriptor(field.getName(),aClass);
                // getReadMethod  获得用于读取属性值的方法;   getWriteMethod(),获得用于写入属性值的方法;
                Method readMethod = ps.getReadMethod();
                Object invoke = readMethod.invoke(dataBean);
                System.out.println("读取:"+invoke);
//                Method writeMethod = ps.getWriteMethod();
//                Object aaabbb = writeMethod.invoke(dataBean, 111);
//                System.out.println("写入:"+aaabbb);
//                System.out.println(annotation);
            }

        }

用到的反射工具类

package com.lqy.redis.util;

import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

/**
 * 〈功能简述〉<br>
 * 〈反射工具类〉
 *
 * @author All en
 * @create 2020/5/6
 * @since 1.0
 */
@Component
public class PublicReflectionUtils {

    /**
     * 功能描述:
     * 〈根据输入对象,查找对象的属性。(包含父类属性)〉
     *
     * @param o 对象
     * @return : java.util.List<java.lang.reflect.Field> 对象属性
     * @author : All En
     * date : 2020/5/6 13:43
     */
    public static Field[] listReflectionField(Object o) throws ClassNotFoundException {
        Class clazz = o.getClass();
        Field[] fields = getAllFields(clazz);
        return fields;
    }


    public static Object getGetMethod(Object ob, String name) throws InvocationTargetException, IllegalAccessException {
        Method[] m = ob.getClass().getMethods();
        for (int i = 0; i < m.length; i++) {
            if (("get" + name).toLowerCase(Locale.ENGLISH).equals(m[i].getName().toLowerCase(Locale.ENGLISH))) {
                return m[i].invoke(ob);
            }
        }
        return null;

    }

    /**
     * 功能描述:
     * 〈获取输入对象的属性〉
     *
     * @param clazz 对象
     * @return : java.lang.reflect.Field[] 对象数据
     * @author : All En
     * date : 2020/5/6 13:43
     */
    private static Field[] getAllFields(Class<?> clazz) throws ClassNotFoundException {
        List<Field> fieldList = new ArrayList<>();
        //对象路径容器
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        //获取Field属性是对象属性。
//        fieldList.addAll(listClassForName(fieldList));
        Field[] fields = new Field[fieldList.size()];
        return fieldList.toArray(fields);
    }

    /**
     * 功能描述:
     * 〈判断Field属性,是否存为对象〉
     *
     * @param fieldList Field属性
     * @return : java.util.List<java.lang.String> 对象数据
     * @author : All En
     * date : 2020/5/6 14:12
     */
    private static List<Field> listClassForName(List<Field> fieldList) throws ClassNotFoundException {
        List<Field> comFieldList = new ArrayList<>();
        for (Field var : fieldList) {
            //判断类型是否为对象路径
            if (var.getGenericType().toString().contains("com")) {
                String[] split = var.getGenericType().toString().split(" ");
                if( split.length >2) {
                    Class z = Class.forName(split[1]);
                    while (z != null) {
                        comFieldList.addAll(new ArrayList<>(Arrays.asList(z.getDeclaredFields())));
                        z = z.getSuperclass();
                    }
                }
            }
        }
        return comFieldList;
    }


    /**
     * 功能描述:〈根据属性名获取对象的属性值〉
     *
     * @param fieldName 属性名
     * @param o         对象
     * @return : java.lang.Object 属性值
     * @author : LL
     * date : 2020.03.19 16:29
     */
    public static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }



    /**
     * 功能描述:
     * 〈循环遍历对象中的属性值,〉
     *
     * @param o              对象
     * @param UnwantedColumn 对象中不需要的列名
     * @return : java.util.List<java.lang.String>
     * @author : All En
     * date : 2020/6/8 10:33
     */
    public static List<String> reflectionFieldResult(Object o, List<String> UnwantedColumn) throws ClassNotFoundException {
        List<String> data = new ArrayList<>();
        Field[] fields = listReflectionField(o);
        for (Field f : fields) {
            List<String> column = UnwantedColumn.stream().filter(v -> v.equals(f.getName())).collect(Collectors.toList());
            if (column.size() == 0) {
                Object value = getFieldValueByName(f.getName(), o);
                if (null == value)
                    data.add("");
                else
                    data.add(String.valueOf(value));
            }
        }
        return data;
    }

    public static void main(String[] args) {
        String a = null;
        System.out.println(String.valueOf(a));
    }
}

用到的读取上下文

package com.lqy.redis.util;

import org.springframework.context.ApplicationContext;

/**
 * 从Spring上下文取出Bean工具类
 *
 * @author ZhuPengWei
 * @date 2018/6/27 18:04
 */
public class SpringApplicationContextUtil {

    private static ApplicationContext applicationContext = null;

    public static void setApplicationContext(ApplicationContext applicationContext) {
        if (SpringApplicationContextUtil.applicationContext == null) {
           SpringApplicationContextUtil.applicationContext = applicationContext;
        }

    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);

    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}


在使用Apache POI结合EasyPOI等库进行Excel导入导出操作时,经常会遇到将实体中标注了`@Head`注解的字段与其对应的中文标题相绑定的需求。为了方便地获取这些字段的中文名称,在实体上可以配合其他元数据注解如`@ExcelEntity`或直接利用反射机制读取相关属性的信息。 下面以一种常见的方式来展示如何在一个标记有`@Sheet`的获得所有标注为`@Head`字段的中文名: ### 方案概述 1. **引入必要的依赖**:确保项目中包含了Apache POI以及EasyPOI(如果选用该库的话)的相关jar包; 2. **定义实体及相应注解**:创建一个用于表示Excel某一行记录的对象模型,并在其各成员变量前加上合适的标签说明其角色; 3. **编写工具方法**:借助Java内置API解析目标Class实例内的私有/公有Field元素,过滤出那些携带有所需元信息的目标组件并整理成易于访问的形式返回给调用者; ### 实现细节 #### 引入依赖 对于Maven工程来说,应在项目的`pom.xml`里加入如下片段来声明所需的外部资源引用: ```xml <!-- Apache POI Core Library --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${apache.poi.version}</version> </dependency> <!-- Optional: EasyPoi extension library for more convenient operations --> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.6.8</version> </dependency> ``` 请注意替换`${apache.poi.version}`为你想要使用的具体版本号。 #### 定义实体 考虑这样一个场景——我们拥有一个人事档案管理系统里的员工基本信息表单模板,它应该具备姓名、性别、出生日期这几个基本要素。此时就可以设计似这样的POJO结构: ```java import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelTarget; // 指明当前是Excel数据映射的目的载体之一 @ExcelTarget("employeeInfo") public class EmployeeDTO implements Serializable { private static final long serialVersionUID = 1L; // 使用EasyPoi提供的@Excel代替原生@Head简化开发过程 @Excel(name="编号", orderNum = "0") private Integer id; @Excel(name="名字", orderNum = "1") private String name; @Excel(name="性别", replace={"男_1","女_2"}, orderNum = "2") private Integer gender; @Excel(name="出生年月日", format = "yyyy-MM-dd", orderNum = "3") private Date birthDate; // Getters and setters... } ``` #### 编写辅助函数 有了上述准备之后,现在我们可以着手编写专门负责检索带有`@Excel/@Head`修饰符的所有非静态成员变量的方法了。这里提供了一种基于反射技术实现思路的例子: ```java import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 获取指定型内所有已由{@link Excel} 或 {@link Head}(视实际环境而定) 注释过的公共&私有字段, * 并将其对应的显示文本抽取出来形成关联列表。 */ public class FieldUtils { /** * 根据传入的class对象查找其中所有的@Excel/@Head字段,并收集它们的序号与中文名称之间的对应关系 * * @param clazz 要分析的具体别 * @return 包含找到的字段位置和文字解释的地图集合 */ public static Map<Integer, String> getAnnotatedFieldNames(Class<?> clazz) { List<Field> annotatedFields = new ArrayList<>(); while (clazz != null && !Object.class.equals(clazz)) { for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Excel.class)) { annotatedFields.add(field); } else if (/* 如果不是EasyPoi则判断是否含有自定义或者其他第三方*/ false) {} } clazz = clazz.getSuperclass(); // 继承链向上追溯直到顶级父级为止 } Map<Integer, String> result = new HashMap<>(annotatedFields.size()); for (Field f : annotatedFields) { Excel excelAnn = f.getAnnotation(Excel.class); if (excelAnn == null || StringUtils.isEmpty(excelAnn.name())) continue; int index = NumberUtils.toInt(StringUtils.defaultIfBlank(excelAnn.orderNum(), "-1"), -1); if(index >= 0){ result.put(index, excelAnn.name()); } } return Collections.unmodifiableMap(result); // 返回不可变视图防止外界误修改内部状态 } } // Usage example within a service method or controller action: Map<Integer, String> columnTitles = FieldUtils.getAnnotatedFieldNames(EmployeeDTO.class); for(Map.Entry<Integer, String> entry : columnTitles.entrySet()){ System.out.println("Column Index:" +entry.getKey()+ ", Title:"+entry.getValue()); } ``` 以上代码展示了怎样通过递归遍历整个继承体系直至根节点处搜集到所有符合条件的候选者。然后按照各自所属的位置索引组织进哈希表当中,便于后续快速定位某个特定单元格应当填充什么样的提示文案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值