JavaDemo——模仿lombok使用注解生成Setter和Getter方法

模仿lombok,使用注解,为类的属性生成Setter方法和Getter方法;

使用自定义注解以及注解解释器,在编译阶段,通过修改抽象语法树(AST)为类添加Getter和Setter方法;

首先maven导入操作AST要用的库(javac也是用的这个),这个库在jdk下lib的tools.jar中,根据自己的jdk目录配置systemPath;(jdk9+似乎需要使用模块化的方式配置)

    <dependency>
	  <groupId>com.sun</groupId>
	  <artifactId>tools</artifactId>
	  <version>1.8.0</version>
	  <scope>system</scope>
	  <systemPath>G:/jdks/jdk-1.8/lib/tools.jar</systemPath>
	</dependency>

项目结构:

编写Demo代码

先定义自定义注解Anno.java

package test;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;

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

@Retention(SOURCE)
@Target(TYPE)
public @interface Anno {

}

关于@Retention,AI的解释:

@Retention 的可用策略(RetentionPolicy)

  1. RetentionPolicy.SOURCE‌:

    • 作用‌:注解仅保留在‌源代码级别‌。
    • 处理时机‌:编译时被编译器丢弃,不会写入编译后的 .class 文件中。
    • 典型用例‌:供编译器检查或生成代码(如 @Override@SuppressWarnings)。
  2. RetentionPolicy.CLASS‌:

    • 作用‌:注解保留到‌字节码文件‌(.class文件)中。
    • 处理时机‌:Java 虚拟机(JVM)加载类时‌不一定保留‌到内存(运行时不可见)。
    • 默认策略‌:若未显式声明 @Retention,则默认为此级别。
  3. RetentionPolicy.RUNTIME‌:

    • 作用‌:注解信息‌永久保留‌,在运行时可通过‌反射机制‌读取。
    • 典型用例‌:框架级注解(如 Spring 的 @Autowired、JUnit 的 @Test)。

 

关键注意事项

  • 默认值‌:未指定 @Retention 时,默认为 RetentionPolicy.CLASS
  • 组合使用‌:通常与 @Target 配合,限制注解的应用目标(如方法、类)。
  • 反射依赖‌:只有 RUNTIME 级别的注解能在运行时通过反射(如 Annotation::getAnnotation)获取。

关于@Target,AI的解释:

@Target 的完整取值列表(ElementType 枚举)

  • ElementType.TYPE‌:
    应用于类、接口、枚举或注解类型声明。
  • ElementType.FIELD‌:
    应用于字段(成员变量)或枚举常量。
  • ElementType.METHOD‌:
    应用于方法声明。
  • ElementType.PARAMETER
### 解决 Lombok 使用时 Excel 输出缺少表头的问题 在使用 Lombok 时,如果发现 Excel 输出文件中没有表头,问题可能与以下因素有关:实体类注解配置、Lombok 的 `@Data` 注解生成getter setter 方法是否正确、以及 EasyExcel 对注解的解析逻辑。以下是详细的解决方案: #### 实体类注解配置 确保实体类中的字段使用了 `@ExcelProperty` 注解,并且该注解的 `value` 属性或 `index` 属性已正确设置[^1]。例如: ```java import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @Data public class Sku { @ExcelProperty(index = 0) private Long id; @ExcelProperty(index = 1) private String name; @ExcelProperty(index = 2) private Double price; } ``` 上述代码中,`@ExcelProperty` 注解用于定义字段对应的 Excel 表头信息。如果未指定 `value` 属性,则默认使用字段名作为表头内容。 #### 检查 Lombok 的 `@Data` 注解 Lombok 的 `@Data` 注解会自动生成 getter setter 方法,但需要注意的是,EasyExcel 在解析实体类时依赖这些方法。如果 Lombok生成逻辑出现问题(例如编译器未正确处理 Lombok 注解),可能会导致表头无法正确解析。可以通过以下方式验证: 1. 确保项目中正确引入了 Lombok 依赖。 2. 检查 IDE 是否启用了对 Lombok 的支持。 3. 手动检查生成getter setter 方法是否正常。 #### 写入逻辑检查 在调用 EasyExcel 的写操作时,需要确保传入的实体类对象与注解配置一致。例如: ```java import com.alibaba.excel.EasyExcel; import java.util.ArrayList; import java.util.List; public class TestWrite { public static void main(String[] args) { String fileName = "demo.xlsx"; List<Sku> data = new ArrayList<>(); Sku sku = new Sku(); sku.setId(1L); sku.setName("Product A"); sku.setPrice(19.99); data.add(sku); EasyExcel.write(fileName, Sku.class).sheet("Sheet1").doWrite(data); } } ``` 上述代码中,`Sku.class` 是带有 `@ExcelProperty` 注解的实体类,`sheet("Sheet1")` 指定了工作表名称。如果省略实体类参数或未正确配置注解,则可能导致表头缺失[^1]。 #### 动态表头设置 如果需要动态生成表头,可以通过自定义方式实现。例如,使用 `Head` 类手动指定表头信息[^2]: ```java import com.alibaba.excel.EasyExcel; import java.util.ArrayList; import java.util.List; public class TestDynamicHead { public static void main(String[] args) { String fileName = "dynamic_head.xlsx"; // 动态表头 List<List<String>> head = new ArrayList<>(); head.add(new ArrayList<String>() {{ add("ID"); }}); head.add(new ArrayList<String>() {{ add("名称"); }}); head.add(new ArrayList<String>() {{ add("价格"); }}); // 数据 List<List<String>> data = new ArrayList<>(); data.add(new ArrayList<String>() {{ add("1"); add("Product A"); add("19.99"); }}); EasyExcel.write(fileName).head(head).sheet("动态表头").doWrite(data); } } ``` 通过这种方式,可以灵活地控制表头内容[^2]。 #### 依赖版本检查 确保使用的 EasyExcel 版本与文档匹配。例如,引用中提到的版本为 `2.1.1`[^1]。如果版本过旧,可能会存在功能限制或 Bug,建议升级到最新稳定版本。 --- ### 注意事项 - 如果仍然无法生成表头,请检查是否有其他逻辑干扰(如自定义监听器或格式化器)。 - 确保实体类字段的注解配置正确,尤其是 `value` 属性是否为空字符串。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值