引言:注解------Java的元编程利器
注解(Annotation)是Java 5引入的一项革命性特性,它允许我们在代码中添加元数据信息,这些信息可以被编译器、开发工具和运行时环境读取和使用。从简单的@Override到复杂的Spring框架注解,注解已经成为现代Java开发的基石。
一、注解基础与内置注解
1.1 Java内置注解详解
java
import java.util.*;
// 演示Java内置注解
public class BuiltInAnnotations {
// 1. @Override - 确保方法正确重写父类方法
@Override
public String toString() {
return "BuiltInAnnotations实例";
}
// 2. @Deprecated - 标记已过时的元素
@Deprecated(
since = "2.0",
forRemoval = true
)
public void oldMethod() {
System.out.println("这是过时的方法,将在未来版本移除");
}
// 3. @SuppressWarnings - 抑制编译器警告
@SuppressWarnings({"unchecked", "rawtypes"})
public void suppressWarningsExample() {
List list = new ArrayList(); // 没有泛型的List
list.add("字符串"); // 会产生警告,但被抑制
}
// 4. @SafeVarargs - 标记可变参数方法是安全的
@SafeVarargs
public static final <T> List<T> asList(T... elements) {
return new ArrayList<>(Arrays.asList(elements));
}
// 5. @FunctionalInterface - 标记函数式接口(Java 8+)
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
// 可以有默认方法
default void printResult(int result) {
System.out.println("结果: " + result);
}
// 可以有静态方法
static Calculator create() {
return (a, b) -> a + b;
}
// 可以重写Object的方法,不计入抽象方法计数
@Override
boolean equals(Object obj);
}
// 6. @Generated - 标记自动生成的代码
@javax.annotation.Generated(
value = "code-generator",
date = "2024-01-01T10:00:00",
comments = "自动生成的代码"
)
public class GeneratedClass {
// 自动生成的代码
}
// 演示注解的目标限制
public static void main(String[] args) {
BuiltInAnnotations demo = new BuiltInAnnotations();
// 使用过时方法会有警告
demo.oldMethod();
// 查看注解信息
System.out.println("=== 注解信息 ===");
try {
// 获取@Override注解信息
Method toStringMethod = BuiltInAnnotations.class.getMethod("toString");
if (toStringMethod.isAnnotationPresent(Override.class)) {
System.out.println("toString方法使用了@Override注解");
}
// 获取@Deprecated注解信息
Method oldMethod = BuiltInAnnotations.class.getMethod("oldMethod");
Deprecated deprecated = oldMethod.getAnnotation(Deprecated.class);
if (deprecated != null) {
System.out.println("oldMethod已过时,since: " + deprecated.since());
System.out.println("是否计划移除: " + deprecated.forRemoval());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
// 7. 重复注解演示(Java 8+)
// 需要先定义容器注解
@Repeatable(Authors.class)
@interface Author {
String name();
String email();
}
@interface Authors {
Author[] value();
}
// 使用重复注解
@Author(name = "张三", email = "zhangsan@example.com")
@Author(name = "李四", email = "lisi@example.com")
class Book {
private String title;
public Book(String title) {
this.title = title;
}
}
// 8. 类型注解(Java 8+)
// 可以注解在任何类型使用的地方
void typeAnnotationExample(
@javax.annotation.NonNull String name, // 参数不为null
List<@javax.annotation.NonNull String> list, // 列表元素不为null
@javax.annotation.Nullable Integer count // 参数可以为null
) {
// 方法体
}
}
1.2 元注解:注解的注解
java
import java.lang.annotation.*;
// 自定义元注解演示
public class MetaAnnotations {
// 1. @Retention - 指定注解的保留策略
@Retention(RetentionPolicy.SOURCE) // 仅源码级别,编译后丢弃
@interface SourceAnnotation {}
@Retention(RetentionPolicy.CLASS) // 类文件级别,运行时不可见
@interface ClassAnnotation {}
@Retention(RetentionPolicy.RUNTIME) // 运行时可见(最常用)
@interface RuntimeAnnotation {}
// 2. @Target - 指定注解可以应用的元素类型
@Target(ElementType.TYPE) // 类、接口、枚举
@interface TypeAnnotation {}
@Target(ElementType.FIELD) // 字段
@interface FieldAnnotation {}
@Target(ElementType.METHOD) // 方法
@interface MethodAnnotation {}
@Target(ElementType.PARAMETER) // 参数
@interface ParameterAnnotation {}
@Target(ElementType.CONSTRUCTOR) // 构造器
@interface ConstructorAnnotation {}
@Target(ElementType.LOCAL_VARIABLE) // 局部变量
@interface LocalVarAnnotation {}
@Target(ElementType.ANNOTATION_TYPE) // 注解类型
@interface AnnotationTypeAnnotation {}
@Target(ElementType.PACKAGE) // 包
@interface PackageAnnotation {}
@Target(ElementType.TYPE_PARAMETER) // 类型参数(Java 8+)
@interface TypeParameterAnnotation {}
@Target(ElementType.TYPE_USE) // 类型使用(Java 8+)
@interface TypeUseAnnotation {}
@Target({ElementType.METHOD, ElementType.FIELD}) // 多个目标
@interface MultiTargetAnnotation {}
// 3. @Documented - 包含在JavaDoc中
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface DocumentedAnnotation {
String value() default "";
}
// 4. @Inherited - 允许子类继承注解
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface InheritedAnnotation {
String value();
}
// 5. @Repeatable - 允许重复注解(Java 8+)
// 已在上面的BuiltInAnnotations中演示
// 应用示例
@TypeAnnotation
@InheritedAnnotation("父类")
class ParentClass {
@FieldAnnotation
private String name;
@MethodAnnotation
@DocumentedAnnotation("这是方法")
public void method(@ParameterAnnotation String param) {
@LocalVarAnnotation
int localVar = 0;
}
@ConstructorAnnotation
public ParentClass() {}
}
// 子类继承@InheritedAnnotation
class ChildClass extends ParentClass {
// 自动继承@InheritedAnnotation("父类")
}
// 类型参数注解(Java 8+)
class GenericClass<@TypeParameterAnnotation T> {
private List<@TypeUseAnnotation T> items;
}
// 包注解需要特殊的package-info.java文件
// package-info.java内容示例:
/*
@PackageAnnotation
package com.example;
import com.example.MetaAnnotations.PackageAnnotation;
*/
public static void main(String[] args) {
System.out.println("=== 元注解演示 ===");
// 检查继承注解
System.out.println("\n1. 检查继承注解:");
System.out.println("ParentClass有@InheritedAnnotation: " +
ParentClass.class.isAnnotationPresent(InheritedAnnotation.class));
System.out.println("ChildClass有@InheritedAnnotation: " +
ChildClass.class.isAnnotationPresent(InheritedAnnotation.class));
System.out.println("ChildClass有@TypeAnnotation: " +
ChildClass.class.isAnnotationPresent(TypeAnnotation.class));
// 检查文档化注解
System.out.println("\n2. 检查注解是否文档化:");
Annotation[] parentAnnotations = ParentClass.class.getAnnotations();
for (Annotation ann : parentAnnotations) {
boolean isDocumented = ann.annotationType()
.isAnnotationPresent(Documented.class);
System.out.println(ann.annotationType().getSimpleName() +
" 是否文档化: " + isDocumented);
}
// 反射获取注解信息
System.out.println("\n3. 反射获取注解详细信息:");
try {
Method method = ParentClass.class.getMethod("method", String.class);
// 方法上的注解
System.out.println("方法注解:");
for (Annotation ann : method.getAnnotations()) {
System.out.println(" - " + ann.annotationType().getSimpleName());
if (ann instanceof DocumentedAnnotation) {
System.out.println(" 值: " + ((DocumentedAnnotation) ann).value());
}
}
// 参数上的注解
System.out.println("参数注解:");
Parameter[] parameters = method.getParameters();
for (Parameter param : parameters) {
for (Annotation ann : param.getAnnotations()) {
System.out.println(" - " + ann.annotationType().getSimpleName());
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
二、自定义注解实战
2.1 创建自定义注解
java
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.time.*;
import java.util.*;
// 自定义注解实战
public class CustomAnnotations {
// 1. 验证注解 - 用于字段验证
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Validate {
int min() default 0;
int max() default Integer.MAX_VALUE;
boolean required() default false;
String regex() default "";
String message() default "验证失败";
}
// 2. 数据库映射注解 - 类似JPA
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@interface Entity {
String tableName() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Column {
String name() default "";
boolean nullable() default true;
boolean unique() default false;
int length() default 255;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Id {
String strategy() default "AUTO";
}
// 3. API文档注解 - 类似Swagger
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@interface ApiOperation {
String value(); // 操作描述
String notes() default ""; // 详细说明
HttpMethod method() default HttpMethod.GET;
String[] tags() default {};
enum HttpMethod {
GET, POST, PUT, DELETE, PATCH
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@interface ApiParam {
String name() default "";
String description() default "";
boolean required() default false;
String defaultValue() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface ApiResponse {
int code();
String message();
Class<?> type() default Void.class;
}
// 4. 缓存注解 - 类似Spring Cache
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Cacheable {
String key() default "";
long ttl() default 3600; // 生存时间(秒)
TimeUnit timeUnit() default TimeUnit.SECONDS;
enum TimeUnit {
SECONDS, MINUTES, HOURS, DAYS
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface CacheEvict {
String key();
boolean allEntries() default false;
}
// 5. 事务注解 - 类似Spring Transactional
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Transactional {
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
enum Propagation {
REQUIRED, REQUIRES_NEW, NESTED, SUPPORTS, NOT_SUPPORTED, NEVER, MANDATORY
}
enum Isolation {
DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
}
}
// 应用示例:用户实体类
@Entity(tableName = "users")
class User {
@Id(strategy = "AUTO")
@Column(name = "user_id", nullable = false)
private Long id;
@Validate(required = true, min = 2, max = 50,
regex = "^[a-zA-Z0-9_]+$",
message = "用户名必须是2-50位的字母数字下划线")
@Column(name = "username", nullable = false, unique = true, length = 50)
private String username;
@Validate(required = true, min = 6,
message = "密码至少6位")
@Column(name = "password", nullable = false, length = 100)
private String password;
@Validate(regex = "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$",
message = "邮箱格式不正确")
@Column(name = "email", length = 100)
private String email;
@Validate(min = 0, max = 150, message = "年龄必须在0-150之间")
@Column(name = "age")
private Integer age;
@Column(name = "created_at", nullable = false)
private LocalDateTime createdAt;
// 构造器、getter、setter省略...
// 验证方法
public List<String> validate() {
List<String> errors = new ArrayList<>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Validate.class)) {
field.setAccessible(true);
Validate validate = field.getAnnotation(Validate.class);
try {
Object value = field.get(this);
// 检查必填
if (validate.required() && value == null) {
errors.add(field.getName() + ": " + validate.message());
continue;
}
if (value == null) {
continue; // 非必填字段为null,跳过其他验证
}
// 字符串类型验证
if (value instanceof String) {
String strValue = (String) value;
// 长度验证
if (strValue.length() < validate.min() ||
strValue.length() > validate.max()) {
errors.add(field.getName() + ": " + validate.message());
}
// 正则验证
if (!validate.regex().isEmpty() &&
!strValue.matches(validate.regex())) {
errors.add(field.getName() + ": " + validate.message());
}
}
// 数字类型验证
if (value instanceof Number) {
Number numValue = (Number) value;
if (numValue.intValue() < validate.min() ||
numValue.intValue() > validate.max()) {
errors.add(field.getName() + ": " + validate.message());
}
}
} catch (IllegalAccessException e) {
errors.add("无法访问字段: " + field.getName());
}
}
}
return errors;
}
}
// 应用示例:用户服务类
class UserService {
@ApiOperation(
value = "创建用户",
notes = "创建新用户账户",
method = ApiOperation.HttpMethod.POST,
tags = {"用户管理"}
)
@ApiResponse(code = 200, message = "创建成功", type = User.class)
@ApiResponse(code = 400, message = "参数错误")
@Transactional(
propagation = Transactional.Propagation.REQUIRED,
isolation = Transactional.Isolation.READ_COMMITTED,
rollbackFor = {RuntimeException.class}
)
public User createUser(
@ApiParam(name = "username", description = "用户名", required = true)
String username,
@ApiParam(name = "password", description = "密码", required = true)
String password,
@ApiParam(name = "email", description = "邮箱")
String email
) {
User user = new User();
// 设置属性...
// 验证
List<String> errors = user.validate();
if (!errors.isEmpty()) {
throw new IllegalArgumentException("验证失败: " + errors);
}
// 保存到数据库...
return user;
}
@ApiOperation(value = "根据ID获取用户", tags = {"用户管理"})
@Cacheable(key = "'user:' + #id", ttl = 300)
public User getUserById(Long id) {
// 模拟从数据库查询
System.out.println("查询数据库,用户ID: " + id);
User user = new User();
// 设置属性...
return user;
}
@ApiOperation(value = "删除用户", tags = {"用户管理"})
@CacheEvict(key = "'user:' + #id")
@Transactional
public void deleteUser(Long id) {
// 删除用户...
}
}
// 注解处理器
static class AnnotationProcessor {
// 生成SQL建表语句
public static String generateCreateTableSQL(Class<?> entityClass) {
if (!entityClass.isAnnotationPresent(Entity.class)) {
throw new IllegalArgumentException("不是实体类");
}
Entity entity = entityClass.getAnnotation(Entity.class);
String tableName = entity.tableName();
if (tableName.isEmpty()) {
tableName = entityClass.getSimpleName().toLowerCase();
}
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE ").append(tableName).append(" (\n");
List<String> columns = new ArrayList<>();
List<String> primaryKeys = new ArrayList<>();
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
String columnName = column.name().isEmpty() ?
field.getName() : column.name();
// 确定列类型
String columnType = getColumnType(field.getType());
// 构建列定义
StringBuilder columnDef = new StringBuilder();
columnDef.append(" ").append(columnName).append(" ").append(columnType);
if (!column.nullable()) {
columnDef.append(" NOT NULL");
}
if (column.unique()) {
columnDef.append(" UNIQUE");
}
if (field.isAnnotationPresent(Id.class)) {
Id id = field.getAnnotation(Id.class);
primaryKeys.add(columnName);
if ("AUTO".equals(id.strategy())) {
if ("BIGINT".equals(columnType)) {
columnDef.append(" AUTO_INCREMENT");
} else if ("INTEGER".equals(columnType)) {
columnDef.append(" AUTOINCREMENT");
}
}
}
columns.add(columnDef.toString());
}
}
sql.append(String.join(",\n", columns));
// 添加主键约束
if (!primaryKeys.isEmpty()) {
sql.append(",\n PRIMARY KEY (")
.append(String.join(", ", primaryKeys))
.append(")");
}
sql.append("\n);");
return sql.toString();
}
private static String getColumnType(Class<?> fieldType) {
if (fieldType == String.class) {
return "VARCHAR(255)";
} else if (fieldType == Long.class || fieldType == long.class) {
return "BIGINT";
} else if (fieldType == Integer.class || fieldType == int.class) {
return "INTEGER";
} else if (fieldType == Double.class || fieldType == double.class) {
return "DOUBLE";
} else if (fieldType == Float.class || fieldType == float.class) {
return "FLOAT";
} else if (fieldType == Boolean.class || fieldType == boolean.class) {
return "BOOLEAN";
} else if (fieldType == LocalDateTime.class) {
return "TIMESTAMP";
} else if (fieldType == Date.class) {
return "DATETIME";
}
return "TEXT";
}
// 生成API文档
public static String generateApiDocumentation(Class<?> serviceClass) {
StringBuilder doc = new StringBuilder();
doc.append("# API文档\n\n");
Method[] methods = serviceClass.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(ApiOperation.class)) {
ApiOperation operation = method.getAnnotation(ApiOperation.class);
doc.append("## ").append(operation.value()).append("\n\n");
doc.append("**方法**: ").append(operation.method()).append("\n\n");
if (!operation.notes().isEmpty()) {
doc.append("**描述**: ").append(operation.notes()).append("\n\n");
}
if (operation.tags().length > 0) {
doc.append("**标签**: ").append(String.join(", ", operation.tags())).append("\n\n");
}
// 参数
Parameter[] parameters = method.getParameters();
if (parameters.length > 0) {
doc.append("### 参数\n\n");
doc.append("| 参数名 | 描述 | 必填 | 默认值 |\n");
doc.append("|--------|------|------|--------|\n");
for (Parameter param : parameters) {
if (param.isAnnotationPresent(ApiParam.class)) {
ApiParam apiParam = param.getAnnotation(ApiParam.class);
String paramName = apiParam.name().isEmpty() ?
param.getName() : apiParam.name();
doc.append("| ").append(paramName)
.append(" | ").append(apiParam.description())
.append(" | ").append(apiParam.required() ? "是" : "否")
.append(" | ").append(apiParam.defaultValue())
.append(" |\n");
}
}
doc.append("\n");
}
// 响应
ApiResponse[] responses = method.getAnnotationsByType(ApiResponse.class);
if (responses.length > 0) {
doc.append("### 响应\n\n");
doc.append("| 状态码 | 描述 | 数据类型 |\n");
doc.append("|--------|------|----------|\n");
for (ApiResponse response : responses) {
doc.append("| ").append(response.code())
.append(" | ").append(response.message())
.append(" | ").append(response.type().getSimpleName())
.append(" |\n");
}
doc.append("\n");
}
}
}
return doc.toString();
}
}
public static void main(String[] args) {
System.out.println("=== 自定义注解实战 ===\n");
// 1. 生成建表SQL
System.out.println("1. 生成User实体建表SQL:");
try {
String createTableSQL = AnnotationProcessor.generateCreateTableSQL(User.class);
System.out.println(createTableSQL);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
}
System.out.println("\n2. 生成API文档:");
String apiDoc = AnnotationProcessor.generateApiDocumentation(UserService.class);
System.out.println(apiDoc);
System.out.println("3. 验证注解演示:");
User user = new User();
// 设置非法数据...
// List<String> errors = user.validate();
// System.out.println("验证错误: " + errors);
}
}
三、注解处理器(APT)
3.1 编译时注解处理器
java
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.*;
import java.io.*;
import java.util.*;
import java.util.stream.*;
/**
* 编译时注解处理器示例
* 需要配置:
* 1. 创建META-INF/services/javax.annotation.processing.Processor文件
* 2. 文件内容:com.example.MyAnnotationProcessor
* 3. 使用javac -processor com.example.MyAnnotationProcessor编译
*/
@SupportedAnnotationTypes("com.example.*")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class AnnotationProcessorExample extends AbstractProcessor {
private Filer filer;
private Messager messager;
private Elements elementUtils;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filer = processingEnv.getFiler();
messager = processingEnv.getMessager();
elementUtils = processingEnv.getElementUtils();
messager.printMessage(Diagnostic.Kind.NOTE, "注解处理器初始化完成");
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// 处理Builder注解
for (Element element : roundEnv.getElementsAnnotatedWith(Builder.class)) {
if (element.getKind() == ElementKind.CLASS) {
generateBuilderClass((TypeElement) element);
}
}
// 处理Singleton注解
for (Element element : roundEnv.getElementsAnnotatedWith(Singleton.class)) {
if (element.getKind() == ElementKind.CLASS) {
generateSingletonCode((TypeElement) element);
}
}
return true;
}
// 定义Builder注解
@Retention(RetentionPolicy.SOURCE) // 仅源码级别
@Target(ElementType.TYPE)
@interface Builder {
String builderClassName() default "";
}
// 定义Singleton注解
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@interface Singleton {
String instanceName() default "INSTANCE";
}
// 示例:被注解的类
@Builder(builderClassName = "PersonBuilder")
class Person {
private String name;
private int age;
// 需要无参构造器
public Person() {}
// getters and setters...
public void setName(String name) { this.name = name; }
public void setAge(int age) { this.age = age; }
}
@Singleton(instanceName = "LOGGER")
class Logger {
public void log(String message) {
System.out.println(message);
}
}
// 生成Builder类
private void generateBuilderClass(TypeElement classElement) {
Builder builderAnnotation = classElement.getAnnotation(Builder.class);
String className = classElement.getSimpleName().toString();
String builderClassName = builderAnnotation.builderClassName().isEmpty() ?
className + "Builder" : builderAnnotation.builderClassName();
String packageName = elementUtils.getPackageOf(classElement).toString();
try {
JavaFileObject builderFile = filer.createSourceFile(
packageName + "." + builderClassName, classElement);
try (PrintWriter writer = new PrintWriter(builderFile.openWriter())) {
// 生成包声明
writer.println("package " + packageName + ";");
writer.println();
writer.println("// 自动生成的Builder类");
writer.println("// 不要手动修改此文件");
writer.println();
writer.println("public class " + builderClassName + " {");
writer.println();
// 生成目标类实例
writer.println(" private " + className + " instance = new " + className + "();");
writer.println();
// 为每个setter方法生成builder方法
List<ExecutableElement> setters = getSetterMethods(classElement);
for (ExecutableElement setter : setters) {
String methodName = setter.getSimpleName().toString();
String fieldName = methodName.substring(3); // 去掉"set"
fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
VariableElement param = setter.getParameters().get(0);
String paramType = param.asType().toString();
String paramName = param.getSimpleName().toString();
writer.println(" public " + builderClassName + " " + fieldName +
"(" + paramType + " " + paramName + ") {");
writer.println(" instance." + methodName + "(" + paramName + ");");
writer.println(" return this;");
writer.println(" }");
writer.println();
}
// 生成build方法
writer.println(" public " + className + " build() {");
writer.println(" return instance;");
writer.println(" }");
writer.println("}");
}
messager.printMessage(Diagnostic.Kind.NOTE,
"生成Builder类: " + builderClassName);
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR,
"无法生成Builder类: " + e.getMessage());
}
}
// 生成单例代码
private void generateSingletonCode(TypeElement classElement) {
Singleton singletonAnnotation = classElement.getAnnotation(Singleton.class);
String className = classElement.getSimpleName().toString();
String instanceName = singletonAnnotation.instanceName();
String packageName = elementUtils.getPackageOf(classElement).toString();
try {
JavaFileObject singletonFile = filer.createSourceFile(
packageName + "." + className + "Singleton", classElement);
try (PrintWriter writer = new PrintWriter(singletonFile.openWriter())) {
writer.println("package " + packageName + ";");
writer.println();
writer.println("// 自动生成的Singleton包装类");
writer.println();
writer.println("public class " + className + "Singleton {");
writer.println();
writer.println(" private static final " + className +
" " + instanceName + " = new " + className + "();");
writer.println();
writer.println(" private " + className + "Singleton() {}");
writer.println();
writer.println(" public static " + className + " getInstance() {");
writer.println(" return " + instanceName + ";");
writer.println(" }");
writer.println("}");
}
messager.printMessage(Diagnostic.Kind.NOTE,
"生成Singleton包装类: " + className + "Singleton");
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR,
"无法生成Singleton类: " + e.getMessage());
}
}
// 获取所有setter方法
private List<ExecutableElement> getSetterMethods(TypeElement classElement) {
return ElementFilter.methodsIn(classElement.getEnclosedElements())
.stream()
.filter(method -> method.getSimpleName().toString().startsWith("set"))
.filter(method -> method.getParameters().size() == 1)
.filter(method -> method.getReturnType().toString().equals("void"))
.collect(Collectors.toList());
}
// 手动编译测试(不使用APT)
public static void testWithoutAPT() {
System.out.println("=== 注解处理器模拟演示 ===");
// 模拟生成的Builder类
System.out.println("\n1. 模拟生成的PersonBuilder:");
System.out.println("""
public class PersonBuilder {
private Person instance = new Person();
public PersonBuilder name(String name) {
instance.setName(name);
return this;
}
public PersonBuilder age(int age) {
instance.setAge(age);
return this;
}
public Person build() {
return instance;
}
}
""");
// 模拟使用
System.out.println("\n2. Builder使用示例:");
System.out.println("""
Person person = new PersonBuilder()
.name("张三")
.age(25)
.build();
""");
// 模拟生成的Singleton类
System.out.println("\n3. 模拟生成的LoggerSingleton:");
System.out.println("""
public class LoggerSingleton {
private static final Logger LOGGER = new Logger();
private LoggerSingleton() {}
public static Logger getInstance() {
return LOGGER;
}
}
""");
}
public static void main(String[] args) {
testWithoutAPT();
}
}
四、运行时注解处理框架
4.1 自定义依赖注入框架
java
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
// 自定义简单的IoC容器
public class SimpleIoCContainer {
// 定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@interface Component {
String value() default "";
Scope scope() default Scope.SINGLETON;
enum Scope {
SINGLETON, PROTOTYPE
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Autowired {
String name() default "";
boolean required() default true;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface PostConstruct {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Configuration {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Bean {
String name() default "";
Scope scope() default Scope.SINGLETON;
}
// IoC容器实现
static class Container {
private final Map<String, Object> singletons = new ConcurrentHashMap<>();
private final Map<String, Class<?>> beanDefinitions = new ConcurrentHashMap<>();
private final Map<String, BeanInfo> beanInfoMap = new ConcurrentHashMap<>();
static class BeanInfo {
Class<?> beanClass;
Component.Scope scope;
String name;
Method factoryMethod;
Object configInstance;
BeanInfo(Class<?> beanClass, Component.Scope scope, String name) {
this.beanClass = beanClass;
this.scope = scope;
this.name = name;
}
}
public void scanPackage(String basePackage) throws Exception {
// 简化版:手动注册,实际应该扫描类路径
System.out.println("扫描包: " + basePackage);
}
public void register(Class<?> clazz) {
if (clazz.isAnnotationPresent(Component.class)) {
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value().isEmpty() ?
getBeanName(clazz) : component.value();
BeanInfo beanInfo = new BeanInfo(
clazz, component.scope(), beanName
);
beanInfoMap.put(beanName, beanInfo);
beanDefinitions.put(beanName, clazz);
System.out.println("注册组件: " + beanName + " -> " + clazz.getName());
}
}
public void registerConfiguration(Class<?> configClass) throws Exception {
if (!configClass.isAnnotationPresent(Configuration.class)) {
return;
}
Object configInstance = configClass.getDeclaredConstructor().newInstance();
for (Method method : configClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Bean.class)) {
Bean bean = method.getAnnotation(Bean.class);
String beanName = bean.name().isEmpty() ?
getBeanName(method.getReturnType()) : bean.name();
BeanInfo beanInfo = new BeanInfo(
method.getReturnType(), bean.scope(), beanName
);
beanInfo.factoryMethod = method;
beanInfo.configInstance = configInstance;
beanInfoMap.put(beanName, beanInfo);
System.out.println("注册Bean: " + beanName + " -> " +
method.getReturnType().getName());
}
}
}
@SuppressWarnings("unchecked")
public <T> T getBean(String name) throws Exception {
// 先从单例池获取
if (singletons.containsKey(name)) {
return (T) singletons.get(name);
}
BeanInfo beanInfo = beanInfoMap.get(name);
if (beanInfo == null) {
throw new RuntimeException("Bean未找到: " + name);
}
// 创建Bean实例
Object bean;
if (beanInfo.factoryMethod != null) {
// 工厂方法创建
bean = beanInfo.factoryMethod.invoke(beanInfo.configInstance);
} else {
// 构造器创建
bean = beanInfo.beanClass.getDeclaredConstructor().newInstance();
}
// 依赖注入
injectDependencies(bean);
// 调用初始化方法
invokePostConstruct(bean);
// 根据Scope处理
if (beanInfo.scope == Component.Scope.SINGLETON) {
singletons.put(name, bean);
}
return (T) bean;
}
public <T> T getBean(Class<T> clazz) throws Exception {
String beanName = getBeanName(clazz);
return getBean(beanName);
}
private void injectDependencies(Object bean) throws Exception {
Class<?> clazz = bean.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
Autowired autowired = field.getAnnotation(Autowired.class);
String dependencyName = autowired.name().isEmpty() ?
getBeanName(field.getType()) : autowired.name();
Object dependency = getBean(dependencyName);
field.setAccessible(true);
field.set(bean, dependency);
System.out.println("注入依赖: " + clazz.getSimpleName() +
"." + field.getName() + " -> " + dependencyName);
}
}
}
private void invokePostConstruct(Object bean) throws Exception {
Class<?> clazz = bean.getClass();
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.setAccessible(true);
method.invoke(bean);
System.out.println("调用初始化方法: " +
clazz.getSimpleName() + "." + method.getName());
}
}
}
private String getBeanName(Class<?> clazz) {
String className = clazz.getSimpleName();
return className.substring(0, 1).toLowerCase() + className.substring(1);
}
}
// 使用示例
// 定义服务接口
interface UserService {
String getUserInfo(Long userId);
}
interface OrderService {
String getOrderInfo(Long orderId);
}
interface EmailService {
void sendEmail(String to, String content);
}
// 实现类
@Component("userService")
class UserServiceImpl implements UserService {
@Autowired
private EmailService emailService;
@Override
public String getUserInfo(Long userId) {
emailService.sendEmail("user@example.com", "查询用户信息");
return "用户信息: ID=" + userId;
}
@PostConstruct
public void init() {
System.out.println("UserService初始化完成");
}
}
@Component(scope = Component.Scope.PROTOTYPE)
class OrderServiceImpl implements OrderService {
@Autowired(required = false) // 非必需依赖
private UserService userService;
@Override
public String getOrderInfo(Long orderId) {
if (userService != null) {
userService.getUserInfo(1L);
}
return "订单信息: ID=" + orderId;
}
}
@Component
class EmailServiceImpl implements EmailService {
@Override
public void sendEmail(String to, String content) {
System.out.println("发送邮件到 " + to + ": " + content);
}
}
// 配置类
@Configuration
class AppConfig {
@Bean(name = "configBean")
public String configString() {
return "配置的字符串Bean";
}
@Bean(scope = Bean.Scope.PROTOTYPE)
public Date currentDate() {
return new Date();
}
}
// 使用容器
public static void main(String[] args) throws Exception {
System.out.println("=== 自定义IoC容器演示 ===\n");
Container container = new Container();
// 注册组件
container.register(UserServiceImpl.class);
container.register(OrderServiceImpl.class);
container.register(EmailServiceImpl.class);
// 注册配置类
container.registerConfiguration(AppConfig.class);
System.out.println("\n=== 获取Bean测试 ===");
// 获取单例Bean
UserService userService = container.getBean("userService");
System.out.println("用户服务: " + userService.getUserInfo(1L));
// 获取原型Bean(每次都是新实例)
OrderService orderService1 = container.getBean(OrderServiceImpl.class);
OrderService orderService2 = container.getBean(OrderServiceImpl.class);
System.out.println("订单服务实例是否相同: " + (orderService1 == orderService2));
// 获取配置的Bean
String configBean = container.getBean("configBean");
System.out.println("配置Bean: " + configBean);
Date date1 = container.getBean(Date.class);
Date date2 = container.getBean(Date.class);
System.out.println("Date实例是否相同: " + (date1 == date2));
System.out.println("\n=== 容器状态 ===");
System.out.println("单例池大小: " + container.singletons.size());
System.out.println("Bean定义数量: " + container.beanInfoMap.size());
}
}
五、注解性能与最佳实践
5.1 注解性能分析与优化
java
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.concurrent.*;
public class AnnotationPerformance {
// 性能测试注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Benchmark {
int iterations() default 1000;
TimeUnit timeUnit() default TimeUnit.NANOSECONDS;
}
// 缓存注解信息,避免重复反射
static class AnnotationCache {
private static final Map<Method, Benchmark> benchmarkCache =
new ConcurrentHashMap<>();
public static Benchmark getBenchmarkAnnotation(Method method) {
return benchmarkCache.computeIfAbsent(method, m ->
m.getAnnotation(Benchmark.class));
}
}
// 性能测试运行器
static class BenchmarkRunner {
public static void runBenchmarks(Object instance) throws Exception {
Class<?> clazz = instance.getClass();
for (Method method : clazz.getDeclaredMethods()) {
Benchmark benchmark = AnnotationCache.getBenchmarkAnnotation(method);
if (benchmark != null) {
runBenchmark(method, instance, benchmark);
}
}
}
private static void runBenchmark(Method method, Object instance,
Benchmark benchmark) throws Exception {
int iterations = benchmark.iterations();
TimeUnit timeUnit = benchmark.timeUnit();
// 预热
for (int i = 0; i < 10; i++) {
method.invoke(instance);
}
// 执行基准测试
long startTime = System.nanoTime();
for (int i = 0; i < iterations; i++) {
method.invoke(instance);
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
// 转换为指定时间单位
double convertedDuration = convertToTimeUnit(duration, timeUnit);
System.out.printf("方法 %s: %d次迭代, 总耗时: %.2f %s, 平均耗时: %.4f %s%n",
method.getName(),
iterations,
convertedDuration,
timeUnit.name().toLowerCase(),
convertedDuration / iterations,
timeUnit.name().toLowerCase());
}
private static double convertToTimeUnit(long nanos, TimeUnit timeUnit) {
switch (timeUnit) {
case NANOSECONDS: return nanos;
case MICROSECONDS: return nanos / 1000.0;
case MILLISECONDS: return nanos / 1_000_000.0;
case SECONDS: return nanos / 1_000_000_000.0;
default: return nanos;
}
}
}
// 测试类
static class PerformanceTest {
@Benchmark(iterations = 10000)
public void fastMethod() {
// 快速方法
Math.sqrt(123.456);
}
@Benchmark(iterations = 1000, timeUnit = TimeUnit.MICROSECONDS)
public void mediumMethod() {
// 中等速度方法
for (int i = 0; i < 100; i++) {
Math.pow(i, 2);
}
}
@Benchmark(iterations = 100, timeUnit = TimeUnit.MILLISECONDS)
public void slowMethod() {
// 慢速方法
try {
Thread.sleep(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 没有注解的方法,不会被测试
public void ignoredMethod() {
System.out.println("这个方法不会被测试");
}
}
// 反射性能对比
static class ReflectionPerformance {
public static void comparePerformance() throws Exception {
PerformanceTest test = new PerformanceTest();
Method method = PerformanceTest.class.getMethod("fastMethod");
int iterations = 100000;
// 直接调用
long start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
test.fastMethod();
}
long directTime = System.nanoTime() - start;
// 反射调用(无缓存)
start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
method.invoke(test);
}
long reflectionTime = System.nanoTime() - start;
// 反射调用(设置可访问)
method.setAccessible(true);
start = System.nanoTime();
for (int i = 0; i < iterations; i++) {
method.invoke(test);
}
long accessibleTime = System.nanoTime() - start;
System.out.println("=== 反射性能对比 ===");
System.out.printf("直接调用: %d ns%n", directTime);
System.out.printf("反射调用: %d ns (慢%.1f倍)%n",
reflectionTime, reflectionTime * 1.0 / directTime);
System.out.printf("反射(setAccessible): %d ns (慢%.1f倍)%n",
accessibleTime, accessibleTime * 1.0 / directTime);
}
}
// 注解最佳实践
static class BestPractices {
public static void showBestPractices() {
System.out.println("\n=== 注解最佳实践 ===");
System.out.println("\n1. 合理选择保留策略:");
System.out.println(" • @Retention(SOURCE) - 编译时处理,不影响运行时性能");
System.out.println(" • @Retention(CLASS) - 默认策略,生成类文件但不加载");
System.out.println(" • @Retention(RUNTIME) - 运行时可用,但有性能开销");
System.out.println("\n2. 明确指定目标:");
System.out.println(" • 使用@Target限制注解使用位置");
System.out.println(" • 避免过于宽泛的目标范围");
System.out.println("\n3. 设计简洁的注解:");
System.out.println(" • 提供合理的默认值");
System.out.println(" • 避免复杂的属性类型");
System.out.println(" • 保持注解的单一职责");
System.out.println("\n4. 性能优化:");
System.out.println(" • 缓存注解信息,避免重复反射");
System.out.println(" • 使用编译时注解处理(APT)减少运行时开销");
System.out.println(" • 考虑使用Annotation Inheritance减少重复注解");
System.out.println("\n5. 文档和命名:");
System.out.println(" • 为自定义注解提供详细的JavaDoc");
System.out.println(" • 使用一致的命名规范");
System.out.println(" • 考虑向后兼容性");
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 注解性能与最佳实践 ===\n");
// 运行基准测试
PerformanceTest test = new PerformanceTest();
BenchmarkRunner.runBenchmarks(test);
System.out.println();
// 反射性能对比
ReflectionPerformance.comparePerformance();
// 最佳实践
BestPractices.showBestPractices();
}
}
总结:注解的强大与智慧
注解的核心价值:
- 元编程能力:在代码中添加元数据,影响编译和运行时行为
- 减少样板代码:通过注解处理器自动生成代码
- 框架集成:Spring、Hibernate等框架的核心机制
- 编译时检查:提供额外的编译时验证
实用建议:
- 优先使用内置注解:如@Override、@Deprecated、@FunctionalInterface
- 合理选择保留策略:避免不必要的运行时开销
- 考虑性能影响:反射调用比直接调用慢10-100倍
- 利用编译时处理:APT可以生成代码,减少运行时负担
适用场景:
- ✅ 适合使用注解:框架扩展、代码生成、配置管理、文档生成
- ⚠️ 谨慎使用注解:性能敏感代码、简单逻辑、过度设计
- ❌ 避免使用注解:复杂的业务逻辑、替代设计模式