900 字
2 分钟
Java注解详解
注解这个东西,刚开始学的时候真没觉得有啥特别的,不就是几个@符号嘛。直到后来用Spring Boot写项目,@Autowired、@Service这些注解用顺手了,才意识到注解的威力。这篇文章把注解的方方面面梳理了一遍,希望能帮到你。
Java注解详解
什么是注解?
注解(Annotation)是Java 5引入的一种元编程特性,说白了就是在代码上贴标签,这些标签可以在编译时、类加载时或运行时被读取和处理。@Override、@Deprecated这些大家应该都用过,但真正理解注解的威力是在用了Spring之后。
注解的作用
- 提供元数据——给代码加额外信息(作者、版本等)
- 编译时检查——比如@Override,写错了编译直接报错
- 代码生成——Lombok的@Getter、@Setter就是靠这个
- 运行时处理——Spring的@Autowired通过反射读取注解
- 配置替代——Spring Boot用注解替代XML配置
内置注解
用于代码的:
@Override——标记重写父类方法@Deprecated——标记已过时@SuppressWarnings——抑制编译器警告@FunctionalInterface——标记函数式接口(Java 8+)@Repeatable——标记注解可重复使用(Java 8+)
元注解(注解的注解):
@Target——指定注解能用在什么地方(类、方法、字段等)@Retention——保留策略:SOURCE(源码)、CLASS(字节码)、RUNTIME(运行时)@Documented——是否包含在Javadoc中@Inherited——是否可以被继承
自定义注解
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface LogExecutionTime { String value() default "";}注解的属性类型有限制:基本类型、String、Class、枚举、注解、以及它们的数组。
元注解详解
@Target
指定注解的目标:
TYPE:类、接口、枚举FIELD:字段METHOD:方法PARAMETER:方法参数CONSTRUCTOR:构造方法LOCAL_VARIABLE:局部变量ANNOTATION_TYPE:注解类型PACKAGE:包TYPE_PARAMETER:类型参数(Java 8+)TYPE_USE:类型使用(Java 8+)
@Retention
指定保留策略:
- SOURCE:只在源码中,编译时丢弃。比如
@Override - CLASS:在class文件中,但运行时不可用。默认值
- RUNTIME:运行时可以通过反射读取。
@Autowired就是这种
@Inherited
如果父类有@Inherited注解,子类会继承它。但只对类上的注解有效,方法和字段上的注解不会继承。
注解的处理
运行时处理(通过反射)
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface Component { String value() default "";}
@Component("userService")public class UserService {}
// 运行时读取注解Class<?> clazz = UserService.class;if (clazz.isAnnotationPresent(Component.class)) { Component component = clazz.getAnnotation(Component.class); System.out.println("Component name: " + component.value());}编译时处理(注解处理器)
编译时处理需要写注解处理器(AbstractProcessor),编译时自动生成代码。Lombok就是这么干的。这个后面有专门的章节讲。
注解的应用场景
- 依赖注入:Spring的
@Autowired、@Component - 配置管理:Spring Boot的
@Configuration、@Bean - 方法路由:Spring MVC的
@GetMapping、@PostMapping - 数据验证:JSR-303的
@NotNull、@Size、@Email - 测试框架:JUnit的
@Test、@Before - 代码生成:Lombok的
@Data、@Builder
常见陷阱
- 保留策略搞错——需要运行时读取但用了SOURCE,反射拿不到
- @Inherited只对类有效——方法和字段上的注解不会被子类继承
- 反射获取注解的性能问题——频繁调用性能差,建议缓存结果
💡 实战贴士: 自定义注解如果只需要编译时处理(代码生成),用
RetentionPolicy.SOURCE就够了,别用RUNTIME,因为运行时反射有性能开销。Lombok的@Getter就是SOURCE级别的,编译完就没了。
分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐
1
Java注解处理器详解
Java 编译时注解处理器是项目里做代码生成时的宝藏工具,写一个注解就能自动生成一大堆重复代码,Lombok的@Getter就是这么来的。
2
Java反射机制详解
Java 反射是Java高级特性中最让我着迷的一个——运行时能看见自己。工作中用Spring的依赖注入时总在想它是怎么做到的,后来才明白反射就是那个幕后推手。
3
Java NIO详解
Java NIO的Selector模型让我第一次感受到了单线程处理万级连接的魅力。相比传统IO的阻塞读写,Channel加Buffer的组合简直是为高性能网络编程量身定做。
4
Java集合框架详解
Java Java集合框架的源码翻来覆去看了好几遍,每次看都有新收获。从ArrayList到ConcurrentHashMap,每个集合背后都有精妙的设计思想。
5
Java Stream API详解
Java Stream API让Java从命令式编程迈向了函数式编程的大门。从filter/map/reduce开始,你会爱上这种链式处理集合数据的写法。






